构建社区连接器

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

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

创建新的 Apps 脚本项目

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

编写连接器代码

每个连接器都必须定义一组特定的函数。通过 这些函数将由托管应用(例如 Looker Studio)执行。您的连接器应处理传入的请求并对其进行响应(有关说明,请参阅社区连接器 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() 参考文档。

Looker Studio 会根据 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;
}

完成项目清单

清单文件包含社区连接器的相关信息, 在 Looker Studio 中部署和使用连接器所需的条件。

要在 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"
 
]
}

如需详细了解 Looker Studio 清单,请参阅清单参考文档

后续步骤

下一步是部署社区连接器