构建社区连接器

构建社区连接器的步骤如下:

  1. 新建 Apps 脚本项目。
  2. 编写连接器代码。
  3. 完成项目清单。

用 Apps 脚本创建新项目

首先,访问 Google Apps 脚本创建一个新项目。Apps 脚本会为您创建默认脚本。您可以随意移除 myFunction 函数和重命名项目。(详细了解 Apps 脚本

编写连接器代码

每个连接器都必须定义一组特定的函数。连接器所在的应用(例如数据洞察)会执行这些函数。您的连接器应处理传入的请求并对其进行响应(有关说明,请参阅社区连接器 API 参考文档)。如果您在开发代码时遇到问题,请参阅调试指南中的帮助信息。

在 getAuthType() 中定义身份验证类型

可调用此函数来确定用于第三方服务的身份验证方法。如需了解详情,请参阅 getAuthType() 参考。AuthType 参考中列出了目前支持的身份验证方法。

例如,以下连接器无需进行身份验证:

npm-downloads/src/auth.js
var cc = DataStudioApp.createCommunityConnector();

// https://developers.google.com/datastudio/connector/reference#getauthtype
function getAuthType() {
  var AuthTypes = cc.AuthType;
  return cc
    .newAuthTypeResponse()
    .setAuthType(AuthTypes.NONE)
    .build();
}

如果您的数据源要求进行 OAuth 2.0 身份验证,请查看 OAuth 2.0 身份验证指南,并向您的连接器中添加其他必要的函数。

通过 getConfig() 定义配置

可调用 getConfig() 函数来获取连接器的配置,包括连接器所需的由用户提供的值。如需了解详情,请参阅 getConfig() 参考。

数据洞察会根据 getConfig() 提供的响应来呈现连接器配置屏幕。ConfigType 参考中列出了所支持的配置元素。

如果您的数据源需要日期作为参数,请调用 config.setDateRangeRequired(true)。如果您需要向用户询问条件性问题或动态配置问题,请参阅分步配置

下例就是一个要求用户输入 NPM 软件包名称代码的连接器。getConfig() 函数中定义了一个信息字段和一个输入字段:

npm-downloads/src/main.js
// https://developers.google.com/datastudio/connector/reference#getconfig
function getConfig() {
  var config = cc.getConfig();

  config
    .newInfo()
    .setId('instructions')
    .setText(
      'Enter npm package names to fetch their download count. An invalid or blank entry will revert to the default value.'
    );

  config
    .newTextInput()
    .setId('package')
    .setName(
      'Enter a single package name or multiple names separated by commas (no spaces!)'
    )
    .setHelpText('e.g. "googleapis" or "package,somepackage,anotherpackage"')
    .setPlaceholder(DEFAULT_PACKAGE)
    .setAllowOverride(true);

  config.setDateRangeRequired(true);

  return config.build();
}

使用 getSchema() 定义字段

可调用此函数来为给定的请求获取架构。任何由 getConfig() 函数定义的配置参数都将在 request 参数中提供。如需了解详情,请参阅 getSchema() 参考

架构可能是固定的,也可能需要您在请求时动态提供,具体取决于连接器的数据源和用户提供的配置。

例如,如果连接器是根据报告 ID 来提取报告数据,可能就无法预先得知为相应报告返回的数据,因而也无法预先得知架构。在这种情况下,getSchema() 可能需要进行数据提取,而且也必须计算架构。

npm-downloads/src/main.js
function getFields() {
  var fields = cc.getFields();
  var types = cc.FieldType;
  var aggregations = cc.AggregationType;

  fields
    .newDimension()
    .setId('packageName')
    .setName('Package')
    .setType(types.TEXT);

  fields
    .newDimension()
    .setId('day')
    .setName('Date')
    .setType(types.YEAR_MONTH_DAY);

  fields
    .newMetric()
    .setId('downloads')
    .setName('Downloads')
    .setType(types.NUMBER)
    .setAggregation(aggregations.SUM);

  return fields;
}

// https://developers.google.com/datastudio/connector/reference#getschema
function getSchema(request) {
  return {schema: getFields().build()};
}

使用 getData() 提取和返回数据

可调用此函数来为给定的请求获取数据。任何由 getConfig() 函数定义的配置参数都将在 request 参数中提供。如需了解详情,请参阅 getData() 参考

您需要额外注意 getData() 请求中的以下参数:

  • lastRefresh
    lastRefresh 是一个时间戳,表示最近一次发出数据刷新请求的时间。使用 new Date(timestampString) 应该就可以解析该值。如果您当前使用了 Apps 脚本缓存服务或任何其他缓存方式,则 lastRefresh 时间戳有助于您决定是要向数据源发出新的提取请求,还是提供缓存中的数据。

  • dateRange
    如果在 getConfig() 中,dateRangeRequired 设为 true,则每次 getData() 调用都会在请求中包含所选日期范围。如需了解详情,请参阅使用日期范围

下例就是根据传入的请求来提取数据并返回软件包统计信息:

npm-downloads/src/main.js
// https://developers.google.com/datastudio/connector/reference#getdata
function getData(request) {
  request.configParams = validateConfig(request.configParams);

  var requestedFields = getFields().forIds(
    request.fields.map(function(field) {
      return field.name;
    })
  );

  try {
    var apiResponse = fetchDataFromApi(request);
    var normalizedResponse = normalizeResponse(request, apiResponse);
    var data = getFormattedData(normalizedResponse, requestedFields);
  } catch (e) {
    cc.newUserError()
      .setDebugText('Error fetching data from API. Exception details: ' + e)
      .setText(
        'The connector has encountered an unrecoverable error. Please try again later, or file an issue if this error persists.'
      )
      .throwException();
  }

  return {
    schema: requestedFields.build(),
    rows: data
  };
}

/**
 * Gets response for UrlFetchApp.
 *
 * @param {Object} request Data request parameters.
 * @returns {string} Response text for UrlFetchApp.
 */
function fetchDataFromApi(request) {
  var url = [
    'https://api.npmjs.org/downloads/range/',
    request.dateRange.startDate,
    ':',
    request.dateRange.endDate,
    '/',
    request.configParams.package
  ].join('');
  var response = UrlFetchApp.fetch(url);
  return response;
}

/**
 * Parses response string into an object. Also standardizes the object structure
 * for single vs multiple packages.
 *
 * @param {Object} request Data request parameters.
 * @param {string} responseString Response from the API.
 * @return {Object} Contains package names as keys and associated download count
 *     information(object) as values.
 */
function normalizeResponse(request, responseString) {
  var response = JSON.parse(responseString);
  var package_list = request.configParams.package.split(',');
  var mapped_response = {};

  if (package_list.length == 1) {
    mapped_response[package_list[0]] = response;
  } else {
    mapped_response = response;
  }

  return mapped_response;
}

/**
 * Formats the parsed response from external data source into correct tabular
 * format and returns only the requestedFields
 *
 * @param {Object} parsedResponse The response string from external data source
 *     parsed into an object in a standard format.
 * @param {Array} requestedFields The fields requested in the getData request.
 * @returns {Array} Array containing rows of data in key-value pairs for each
 *     field.
 */
function getFormattedData(response, requestedFields) {
  var data = [];
  Object.keys(response).map(function(packageName) {
    var package = response[packageName];
    var downloadData = package.downloads;
    var formattedData = downloadData.map(function(dailyDownload) {
      return formatData(requestedFields, packageName, dailyDownload);
    });
    data = data.concat(formattedData);
  });
  return data;
}

完成项目清单

清单文件包含了社区连接器的相关信息,在数据洞察中部署和使用该连接器时,需要用到这些信息。

要在 Apps 脚本开发环境中修改清单文件,请点击查看菜单,然后点击显示清单文件。这将创建一个新的 appsscript.json 清单文件。

更新该清单,使其包含以下数据:

npm-downloads/src/appsscript.json
{
  "dependencies": {
    "libraries": []
  },
  "dataStudio": {
    "name": "npm Downloads",
    "logoUrl": "https://raw.githubusercontent.com/npm/logos/master/npm%20square/n-64.png",
    "company": "Google Data Studio Developer Relations",
    "companyUrl": "https://developers.google.com/datastudio/",
    "addonUrl": "https://github.com/googledatastudio/community-connectors/tree/master/npm-downloads#readme",
    "supportUrl": "https://github.com/googledatastudio/community-connectors/issues",
    "description": "Get npm package download counts.",
    "sources": ["npm"],
    "templates": {
      "default": "1twu0sHjqR5dELAPyGJcw4GS3-D0_NTrQ"
    }
  },
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request"
  ]
}

要详细了解数据洞察清单,请参阅清单参考

开源社区连接器

您可以浏览开源社区连接器,以获取其他示例代码。这些示例着重说明了社区连接器开发方面的各种用例和最佳做法。

后续步骤

下一步是部署社区连接器