Build a Community Connector

The steps to building a Community Connector are:

  1. Create a new Apps Script project.
  2. Write the connector code.
  3. Complete the project manifest.

Create a new project in Apps Script

Visit Google Apps Script to create a new project. Apps Script will create a default script for you. Feel free to remove the myFunction function and rename the project. (Learn more about Apps Script)

Write the connector code

Every connector is required to have a specific set of functions defined. The hosting application (e.g. Data Studio) will execute these functions. Your connector is expected to handle incoming requests and respond as described in the Community Connector API reference. If you face issues while developing your code, read the debugging guide for help.

Define configuration via getConfig()

The getConfig() function is called to get the configuration for the connector, including the user provided values that your connector requires. See getConfig() reference for details.

Based on the response provided by getConfig(), Data Studio will render the connector configuration screen. The configuration elements supported are listed in ConfigType reference.

If your data source requires date as a parameter, call config.setDateRangeRequired(true). If your data source does not require date as a parameter, you can omit this.

The following is an example of a connector that requires the user to enter an npm package name code. An info and an input field are defined in the getConfig() function:

function getConfig() {
  var cc = DataStudioApp.createCommunityConnector();
  var config = cc.getConfig();

  config.newInfo()
      .setId('instructions')
      .setText('Enter npm package names to fetch their download count.');

  config.newTextInput()
      .setId('package')
      .setName('Enter a single package name.')
      .setHelpText('for example, googleapis or lighthouse')
      .setPlaceholder('googleapis')
      .setAllowOverride(true);

  config.setDateRangeRequired(true);

  return config.build();
}

Define the data schema with getSchema()

This function is called to get the schema for the given request. Any configuration parameters defined by the getConfig() function will be provided in the request argument. See getSchema() reference for details.

Depending on your connector's data source and the configuration provided by the user, the schema may be fixed or you may have to dynamically provide this at request time.

For example, if a connector is fetching report data based on a Report ID, the data returned for that report and hence the schema may not be known beforehand. In this case getSchema() may require a data fetch and the schema will have to be calculated.

function getFields() {
  var cc = DataStudioApp.createCommunityConnector();
  var fields = cc.getFields();
  var types = cc.FieldType;
  var aggregations = cc.AggregationType;

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

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

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

  return fields;

}

function getSchema(request) {
  var fields = getFields().build();
  return { 'schema': fields };
}

Fetch and return data with getData()

This function is called to get data for the given request. Any configuration parameters defined by the getConfig() function will be provided in the request argument. See getData() reference for details.

The following parameters from the getData() request require additional attention:

  • sampleExtraction
    If sampleExtraction is true, then the request is for the automatic semantic type detection process. Rather than returning the entire data set, you can choose to return a subset, or first n number of records, or predefined values for each fields. This helps with API rate limits and also makes the semantic detection process faster. However, you can choose not to handle sampleExtraction separately and let semantic detection use the entire data set. Note that in this scenario, your data set will get queried at least twice.

  • lastRefresh
    lastRefresh represents a timestamp that marks the time of the most recent request for a refresh of data. You should be able to parse the value with new Date(timestampString). If you are using Apps Script Cache Service or any other caching method, the lastRefresh timestamp can help you to determine whether to make a new fetch request to the data source or serve data from the cache.

  • dateRange
    If dateRangeRequired is set to true in getConfig(), each getData() call will contain the selected date range in the request. See Working with Date Ranges for more details.

The following example fetches data based on the incoming request and returns the package statistics:

function responseToRows(requestedFields, response, packageName) {
  // Transform parsed data and filter for requested fields
  return response.map(function(dailyDownload) {
    var row = [];
    requestedFields.asArray().forEach(function (field) {
      switch (field.getId()) {
        case 'day':
          return row.push(dailyDownload.day.replace(/-/g, ''));
        case 'downloads':
          return row.push(dailyDownload.downloads);
        case 'packageName':
          return row.push(packageName);
        default:
          return row.push('');
      }
    });
    return { values: row };
  });
}

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

  // Fetch and parse data from API
  var url = [
    'https://api.npmjs.org/downloads/range/',
    request.dateRange.startDate,
    ':',
    request.dateRange.endDate,
    '/',
    request.configParams.package
  ];
  var response = UrlFetchApp.fetch(url.join(''));
  var parsedResponse = JSON.parse(response).downloads;
  var rows = responseToRows(requestedFields, parsedResponse, request.configParams.package);

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

Define authentication type in getAuthType()

This function is called to identify the authentication method used for the 3rd-party service. See getAuthType() reference for details. Currently supported authentication methods are listed in AuthType reference.

For example, the following connector does not require authentication:

function getAuthType() {
  var response = { type: 'NONE' };
  return response;
}

If your data source requires OAuth 2.0 authentication, view the OAuth 2.0 authentication guide and add the additional required functions to your connector.

Complete the project manifest

The manifest file contains information about your Community Connector that is required to deploy and use your connector in Data Studio.

To edit the manifest file in the Apps Script development environment, click on the View menu and click Show manifest file. This will create a new appsscript.json manifest file.

Update the manifest to include the following data:

{
  "dataStudio": {
    "name": "npm Downloads - Build Guide",
    "logoUrl": "https://raw.githubusercontent.com/npm/logos/master/%22npm%22%20lockup/npm-logo-simplifed-with-white-space.png",
    "company": "Build Guide User",
    "companyUrl": "https://developers.google.com/datastudio/",
    "addonUrl": "https://github.com/google/datastudio/tree/master/community-connectors/npm-downloads",
    "supportUrl": "https://github.com/google/datastudio/issues",
    "description": "Get npm package download counts.",
    "sources": ["npm"]
  }
}

For details on Data Studio manifest, see the reference manifest reference.

Open Source Community Connectors

You can explore Open Source Community Connectors for additional example code. The examples highlight various use cases and best practices for Community Connector development.

Next steps

The next step will be to deploy your Community Connector.