Custom Connectors

Connector Dev Studio

Data is the foundation of everything you do in Domo.  In order to build that foundation, connectors are available to access all your relevant data. A connector pulls data from a data source and makes it accessible inside Domo. Connectors can be setup to pull data on a schedule and append or replace the existing content from that data source.

To support data sources that are not available in Domo’s current catalog of connectors, Domo has created an intuitive web-based Integrated Development Environment (IDE) for building custom connectors.

The connector development process leverages the JavaScript language in conjunction with added convenience methods. If you are comfortable with the JavaScript language, it is possible to build a connector now. Never touched JavaScript before today or need to brush up? Do a search for a JavaScript fundamentals course.  There are several good ones available online.

Getting Started

Before building a new connector make sure one that meets your use case doesn’t already exist. You can see existing connectors by going to the Data Center in Domo and selecting “+Add DataSet.”

The connectors page will display the current connectors:

Connectors already in Domo

Sample Connectors

 

Give it a Test Run

If your desired connector does not exist, you can use the Connector Dev Studio to build your own. The following sections will give you examples and explanations of how to use the tools. If you don’t need the explanations or want to try it out, jump straight to the IDE by selecting the “Build a Connector now” button below.

Build a Connector now

If you want more understanding of how to better work with the Connector Dev Studio then continue reading below or jump to the section of interest by using the navigation on the left.

Process Overview

There are four steps to build a connector:

  • Upload images
  • Configure user authentication
  • Configure selectable reports
  • Define how data is processed

Uploading images

It is important to identify your connector by providing images. The specifications for the four different icons are detailed above the sample images in the Studio.

uploadimages

If you want to get started now, the four images you need for a connector are:

  • Icon with background (512 x 512 pixels)
  • Icon, no background (512 x 512 pixels)
  • Logo with background (512 x 512 pixels)
  • Logo banner, no background (1024 x 512 pixels)

 

If you don’t add your own images, the default ones will be used to represent your connector in the IDE.

Configure user authentication

The Connector Builder provides four different authentication methods. For a detailed description of the different methods, see the Authentication section.

After selecting an authentication method write a code block to validate the API’s credentials.

configuration

Example:

httprequest.addHeader('Authorization', 'Basic ' + DOMO.b64EncodeUnicode(metadata.account.username + ':' + metadata.account.password));

var res = httprequest.get('https://samplecrm.domo.com/samplecrm');

DOMO.log('res: ' + res);

if(res.indexOf('Account.Name') > 0){auth.authenticationSuccess();}
else{auth.authenticationFailed('Your username and password are incorrect');}

The code block needs to set auth.authenticationSuccess(); or auth.authenticationFailed(‘Your username and password are incorrect’);

Configure selectable reports

Connectors are comprised of a series of reports, which define groups of data that a user will select when using this connector in Domo. You will need to define the reports for your connector on this step.

configureReports

Sample with existing reports

Define how the data is processed

On this step define how your connector will process data.  The script should retrieve the data, parse it if needed, and then store it in Domo.

downloadprocess

 

Authentication

To build your own connector you will need to know how to authenticate to your target data system. The IDE supports 4 different authentication schemes:

  1. None when the API does not require any authentication
  2. Username with password is most commonly used with Basic Authentication.  When authenticating with Basic Authentication the user passes an Authorization header with a Base64Encoded <username>:<password>. Example:
httprequest.addHeader('Authorization', 'Basic ' + DOMO.b64EncodeUnicode(metadata.account.username + ':' + metadata.account.password));

3. API Key is generally a non-expiring key or token passed in as a header or a query parameter. Example:

httprequest.addHeader('API-KEY', metadata.account.apikey); or
httprequest.get('https://samplecrm.domo.com/samplecrm?apikey=' + apikey);

4. OAuth2 uses a client side and server flow to generate token that can be used to authenticate to an API. For detailed information on OAuth2 please visit: http://oauth.net/2/

The Connector Dev Studio provides an interface to configure OAuth2 for development purposes. It will present you with a screen like this:

oauth2

Consult the API documentation for the API you are using to determine the best way to configure this.

What if I need a different type of authentication?

The Dev Studio does not  support any other authentication methods but you can use the Domo APIs to write your own program. Click here to learn more about building your own program using Domo APIs.

Data Processing

This is an example of a data processing script.

DOMO.log('metadata.account.username: ' + metadata.account.username);  //example
DOMO.log('metadata.account.password: ' + metadata.account.password);  //test
DOMO.log('metadata.report: ' + metadata.report); //Opportunities

if(metadata.report == 'Opportunities'){
httprequest.addHeader('Authorization', 'Basic ' + DOMO.b64EncodeUnicode(metadata.account.username + ':' + metadata.account.password));

//example of how to access "Pull data from the last x day(s)" value:

//var res = httprequest.get('https://samplecrm.domo.com/samplecrm?days=' + metadata.days);
var res = httprequest.get('https://samplecrm.domo.com/samplecrm');
DOMO.log('res: ' + res);
var lines = res.split('r');
var header = lines[0].split(',');

//There are three data types: datagrid.DATA_TYPE_STRING, datagrid.DATA_TYPE_DOUBLE and datagrid.DATA_TYPE_DATETIME

// date format needs to be yyyy-MM-dd'T'HH:mm:ss

datagrid.addColumn('Account.Id', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Account.Industry', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Account.Name', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Amount', datagrid.DATA_TYPE_DOUBLE);
datagrid.addColumn('CloseDate', datagrid.DATA_TYPE_DATETIME);
datagrid.addColumn('CloseDate', datagrid.DATA_TYPE_DATETIME);
datagrid.addColumn('Id', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('IsClosed', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('IsWon', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('LastActivityDate', datagrid.DATA_TYPE_DATETIME);
datagrid.addColumn('LastModifiedDate', datagrid.DATA_TYPE_DATETIME);
datagrid.addColumn('LeadSource', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Name', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('NextStep', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Probability', datagrid.DATA_TYPE_DOUBLE);
datagrid.addColumn('StageName', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Type', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('ForecastCategoryName', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Strategic_Account__c', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Forecasted_ACV__c', datagrid.DATA_TYPE_DOUBLE);
datagrid.addColumn('Competitor__c', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Owner.CreatedDate', datagrid.DATA_TYPE_DATETIME);
datagrid.addColumn('Owner.Email', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Owner.FullPhotoUrl', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Owner.Id', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Owner.IsActive', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Owner.Manager', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Owner.Name', datagrid.DATA_TYPE_STRING);
datagrid.addColumn('Owner.UserRole.Name', datagrid.DATA_TYPE_STRING);

for(var i = 1; i < lines.length; i++){
 console.log('line: ' +  lines[i]); ///For heavy logging use browser console logging
 var rows = lines[i].split(',');
 for(var j = 0; j < rows.length; j++){
  if(j == 4){datagrid.addCell(rows[j] + 'T00:00:00');}
  else if(j == 9){datagrid.addCell(rows[j] + 'T00:00:00');}
 else{datagrid.addCell(rows[j]);}
 }
 datagrid.endRow();
}
} else {
DOMO.log(metadata.report + ' is not a supported report.');
datagrid.error(0, metadata.report + ' is not a supported report.');
}

See the reference section for specifics.

Coding

After connecting to your data system the Dev Studio will provide you with a development environment page where you can write custom code to pull the data into Domo.

Important to note: while the IDE runs your code client side in your chosen browser, your deployed code will run in the Nashorn engine found in Java 8. Make sure you follow the best practices of that engine and only use the objects and methods that it supports.  See the ECMAScript Language Specification for details.

For example Xmlhttprequest is not supported you will need to use httprequest in its place. Sample call:

httprequest.get('https://samplecrm.domo.com/samplecrm');

Reference

Auth

Method Arguments Return Example Notes
authenticationSuccess none none auth.authenticationSuccess() During the credential validation process notifies the user their credentials are valid.
authenticationFailed error none auth.authenticationFailed(‘Your username and password are incorrect’) During the credential validation process notifies the user their credentials are invalid.

 


DataGrid

Method Arguments Return Example Notes
addCell value none Datagrid.addCell(‘a123845’)
addColumn name, type none datagrid.addColumn(‘Account.Id’, datagrid.DATA_TYPE_STRING)
endRow none none datagrid.endRow Commits a row and starts a new one.
error code, error none datagrid.error(0, metadata.report + ‘ is not a supported report.’); Ends the processing of data and gives an error to the user
datagrid.DATA_TYPE_STRING none none datagrid.addColumn(‘Account.Id’, datagrid.DATA_TYPE_STRING) Constant
datagrid.DATA_TYPE_DOUBLE none none datagrid.addColumn(‘amount’, datagrid.DATA_TYPE_DOUBLE) Constant
datagrid.DATA_TYPE_DATETIME none none datagrid.addColumn(‘createdDate’, datagrid.DATA_TYPE_DATETIME) Constant

 

DOMO

Method Arguments Return Example Notes
b64EncodeUnicode value String DOMO.b64EncodeUnicode(metadata.account.username + ‘:’ + metadata.account.password) Used to base64 encode a string
log value none DOMO.log(‘metadata.report: ‘ + metadata.report); Prints logging to console.  Make sure you remove credentials that you are logging before submitting your connector.

 

 

HTTP Request

Method Arguments Return Example Notes
addHeader name, value none httprequest.addHeader(‘Authorization’, ‘Basic ‘ + DOMO.b64EncodeUnicode(metadata.account.username + ‘:’ + metadata.account.password))
addParameter name, value none httprequest.addParameter(‘days’, metadata.days)
clearParameters url String
clearHeaders url String
get url String httprequest.get(‘https://samplecrm.domo.com/samplecrm’);
post url String  httprequest.post(‘https://samplecrm.domo.com/samplecrm’);

Example Connector: Sample CRM

configure reports

Credentials

Username: example
Password: test

Authentication Block:

DOMO.log('metadata.account.username: ' + metadata.account.username);    //example
DOMO.log('metadata.account.password: ' + metadata.account.password);  //test

DOMO.log(DOMO.b64EncodeUnicode(metadata.account.username + ':' + metadata.account.password));

httprequest.addHeader('Authorization', 'Basic ' + DOMO.b64EncodeUnicode(metadata.account.username + ':' + metadata.account.password));

var res = httprequest.get('https://samplecrm.domo.com/samplecrm');  

DOMO.log('res: ' + res);

if(res.indexOf('Account.Name') > 0){auth.authenticationSuccess();}
else{auth.authenticationFailed('Your username and password are incorrect');}

Reports:

  • Opportunities

Data processing block:

DOMO.log('metadata.account.username: ' + metadata.account.username);  //example 
DOMO.log('metadata.account.password: ' + metadata.account.password);  //test 
DOMO.log('metadata.report: ' + metadata.report); //Opportunities

if(metadata.report == 'Opportunities'){

    httprequest.addHeader('Authorization', 'Basic ' + DOMO.b64EncodeUnicode(metadata.account.username + ':' + metadata.account.password));

  //example of how to access "Pull data from the last x day(s)" value:
    //var res = httprequest.get('https://samplecrm.domo.com/samplecrm?days=' + metadata.days);  

    var res = httprequest.get('https://samplecrm.domo.com/samplecrm');

    DOMO.log('res: ' + res);

    var lines = res.split('r');

    var header = lines[0].split(',');

      //There are three data types: datagrid.DATA_TYPE_STRING, datagrid.DATA_TYPE_DOUBLE and datagrid.DATA_TYPE_DATETIME
      // date format needs to be yyyy-MM-dd'T'HH:mm:ss

    datagrid.addColumn('Account.Id', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Account.Industry', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Account.Name', datagrid.DATA_TYPE_STRING); 
    datagrid.addColumn('Amount', datagrid.DATA_TYPE_DOUBLE);
    datagrid.addColumn('CloseDate', datagrid.DATA_TYPE_DATETIME);
    datagrid.addColumn('CloseDate', datagrid.DATA_TYPE_DATETIME);
    datagrid.addColumn('Id', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('IsClosed', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('IsWon', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('LastActivityDate', datagrid.DATA_TYPE_DATETIME);
    datagrid.addColumn('LastModifiedDate', datagrid.DATA_TYPE_DATETIME);
    datagrid.addColumn('LeadSource', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Name', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('NextStep', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Probability', datagrid.DATA_TYPE_DOUBLE);
    datagrid.addColumn('StageName', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Type', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('ForecastCategoryName', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Strategic_Account__c', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Forecasted_ACV__c', datagrid.DATA_TYPE_DOUBLE);
    datagrid.addColumn('Competitor__c', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Owner.CreatedDate', datagrid.DATA_TYPE_DATETIME);
    datagrid.addColumn('Owner.Email', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Owner.FullPhotoUrl', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Owner.Id', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Owner.IsActive', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Owner.Manager', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Owner.Name', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Owner.UserRole.Name', datagrid.DATA_TYPE_STRING);

    for(var i = 1; i < lines.length; i++){

        console.log('line: ' +  lines[i]); ///For heavy logging use browser console logging

        var rows = lines[i].split(',');

        for(var j = 0; j < rows.length; j++){

          if(j == 4){datagrid.addCell(rows[j] + 'T00:00:00');}
          else if(j == 9){datagrid.addCell(rows[j] + 'T00:00:00');}
          else{datagrid.addCell(rows[j]);}

        }

        datagrid.endRow();

    }

} else {

  DOMO.log(metadata.report + ' is not a supported report.');
  datagrid.error(0, metadata.report + ' is not a supported report.');

}

Example Connector: USGS

configure reports

Credentials

None

Authentication Block:

var res = httprequest.get('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson');  

DOMO.log('res: ' + res);

if(res.indexOf('FeatureCollection') > 0){auth.authenticationSuccess();}
else{auth.authenticationFailed('Error connecting to earthquake.usgs.gov');}

Reports:

  • Past Hour
  • Past Day
  • Past 7 Days
  • Past 30 Days
  • Pull data from the last X day(s)

Data processing block:

DOMO.log('metadata.report: ' + metadata.report);

if(metadata.report == 'Past Hour'){pastHour();}
else if(metadata.report == 'Past Day'){pastDay();}
else if(metadata.report == 'Past 7 Days'){past7Days();}
else if(metadata.report == 'Past 30 Days'){past30Days();}
else if(metadata.report == 'Pull data from the last X day(s)'){pastXDays();}
else {
  DOMO.log(metadata.report + ' is not a supported report.');
  datagrid.error(0, metadata.report + ' is not a supported report.');
}

//functions

  function pastHour(){
    DOMO.log('pastHour');

    processRecords('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson');

  }

  function pastDay(){
    DOMO.log('pastDay');

    processRecords('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson');

  }

  function past7Days(){
    DOMO.log('past7Days');

    processRecords('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson');

  }

  function past30Days(){
    DOMO.log('past30Days');

    processRecords('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson');

  }

  function pastXDays(){
    DOMO.log('pastXDays');

    processRecords('http://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=' + calculateEndDate() + '&endtime=' + currentDate());
  }

  function calculateEndDate(){

    var now = new Date();
    var end = new Date( new Date().getTime() - (metadata.days * 1000 * 60 * 60 * 24) );

    DOMO.log('Start: ' + now);
    DOMO.log('End: ' + end);

    return end.getFullYear() + '-' + addOneLeadingZero(end.getMonth() + 1) + '-' + addOneLeadingZero(end.getDate());

  }

  function currentDate(){

    var now = new Date();

    return now.getFullYear() + '-' + addOneLeadingZero(now.getMonth() + 1) + '-' + addOneLeadingZero(now.getDate());

  }

  function processRecords(url){

    var res = httprequest.get(url);
    DOMO.log('res' + res);

    var data = JSON.parse(res).features;

    datagrid.addColumn('Place', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Magnitude', datagrid.DATA_TYPE_STRING);
    datagrid.addColumn('Time', datagrid.DATA_TYPE_DATETIME); // date format needs to be yyyy-MM-dd'T'HH:mm:ss
    datagrid.addColumn('URL', datagrid.DATA_TYPE_STRING);

    DOMO.log('data: ');

    for(var i = 0; i < data.length; i++){

        var quakeDetails = data[i].properties;

        datagrid.addCell(quakeDetails.place);
        datagrid.addCell(quakeDetails.mag);
        datagrid.addCell(formatTime(quakeDetails.time));
        datagrid.addCell(quakeDetails.url);

        datagrid.endRow();

    }

  }

  function formatTime(value){

    var d = new Date(value);

    return d.getFullYear() + '-' +  addOneLeadingZero(d.getMonth() + 1) + '-' + addOneLeadingZero(d.getDate()) + '-' + 'T' + addOneLeadingZero(d.getHours() + 1) + ':' + addOneLeadingZero(d.getMinutes() + 1) + ':' + addOneLeadingZero(d.getSeconds() + 1);
  }

  function addOneLeadingZero(value){

    if(value < 10 && value > -10){ value = '0' + value;}

    return value;
  }

Build a Connector Now

Select the button below to start building your own custom connector

Build a Connector now

Help & Support

Domo is committed to answering all of your App development questions, even when you’re burning the midnight oil.

Try us: Our technical support consultants are there 24/7 to provide world-class service and help you make the most of your Domo experience.

801-805-9505

domoconnectorsupport@domo.com