Node.js SDK for ContactHub
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
example
flow-typed/npm
src
test
.babelrc
.dockerignore
.eslintrc
.flowconfig
.gitignore
.hophoprc
.travis.yml
CHANGELOG.md
CONTRIBUTING.md
Dockerfile
LICENSE
README.md
index.js
package.json 1.1.2 Jul 4, 2018

README.md

Contacthub nodejs SDK

Build Status GitHub release npm version

Node.js SDK for the Contacthub API.

Requirements and design

This library requires Node.js v6 or later.

All asynchronous operations return a Promise.

Flow type annotations are used throughout the library, and can be leveraged if you use Flow in a project that depends on this library.

Installation

npm install --save contacthub-sdk-nodejs 

Quick start

const ContactHub = require('contacthub-sdk-nodejs');

const ch = new ContactHub({
  token: 'YOUR_TOKEN',
  workspaceId: 'YOUR_WORKSPACE_ID',
  nodeId: 'YOUR_NODE_ID'
});

ch.getCustomer('CUSTOMER_ID').then(customer => {
  if (customer.base && customer.base.firstName && customer.base.lastName) {
    console.log(`${customer.base.firstName} ${customer.base.lastName}`);
  }
});

Initializing and authenticating

All the functions provided by the SDK are exposed as methods of the ContactHub object prototype.

To create a new instance, you need three authentication parameters: token, workspaceId and nodeId. You can find them using the Contacthub UI.

const ch = new ContactHub({
  token: 'YOUR_TOKEN',
  workspaceId: 'YOUR_WORKSPACE_ID',
  nodeId: 'YOUR_NODE_ID'
});

The ch object uses the appropriate authentication parameters for all of the methods listed below.

If you need to work with more than one workspace or node, or if you want to use different tokens, you can instantiate multiple Contacthub objects.

Session API

createSessionId

Generates a new random sessionId to use in Contacthub events.

const sessionId = ch.createSessionId();

addCustomerSession

Reconciles a sessionId with an existing Customer. Use this if you want to associate anonymous events (containing a sessionId) with an existing customerId.

Returns a Promise that resolves to true if the sessionId has been successfully reconciled.

ch.addCustomerSession(customerId, sessionId)

Event API

addEvent

Adds a new Event.

Returns a Promise that resolves to true if the API has successfully queued the event for insertion. The API will then process the queue asynchronously, and it can take a few seconds for an event to actually be stored.

addEvent(event)

The event parameter is an object that can contain the following properties:

  • customerId

    The ID of the Customer associated with the event.

  • externalId

    The externalId of the Customer associated with the event.

  • sessionId

    The ID of the session associated with the event.

  • context

    One of WEB,MOBILE,ECOMMERCE,RETAIL,SOCIAL,DIGITAL_CAMPAIGN,CONTACT_CENTER,IOT,OTHER.

  • contextInfo

    An Object conforming to the JSON schema defined for the specified context. All schemas are available at this link.

  • type

    A valid event type. All event types are listed at this link.

  • properties

    An object conforming to the JSON schema defined for the specified event type. All schemas are available at this link.

The required keys are context, type and properties, others are optional.

You must specify one of customerId, externalId or sessionId. If you don't have any Customer information (for example, the customer is not logged in) you should use a sessionId. This enables you to later reconcile all the events in the same session with a Customer, when they log in.

Example:

The following is an example of a valid event object:

const event = {
  sessionId: 'ses123',
  context: 'WEB',
  contextInfo: {
    client: {
      ip: '1.2.3.4'
    },
    user: {
      id: 'username1'
    }
  },
  type: 'viewedPage',
  properties: {
    title: 'Page Title',
    url: 'http://www.example.com'
  }
};

getEvent

Retrieves an event by its ID.

Returns a Promise that resolves to an Event object.

ch.getEvent(eventId);

getEvents

Retrieves all the events for a customer.

Returns a Promise that resolves to a PaginatedResult<Event> object.

ch.getEvents(customerId);

Customer API

addCustomer

Creates a new Customer.

Returns a Promise that resolves to a Customer object, including the id that was assigned by the API.

ch.addCustomer(customerData)

The customerData parameter is an object that can contain the following properties:

  • externalId

    A string identifying the customer in your own systems.

  • base

    An object conforming to the JSON schema for Base Properties.

  • consents

    An object conforming to the JSON schema for Consents.

  • extended

    An object conforming the JSON schema for Extended Properties. Extended properties can be customised for each Contacthub Workspace.

  • extra

    A string containing extra data about the customer.

  • tags

    An object conforming to the JSON schema for Tags.

All properties are optional, but the object must contain at least one of the following:

  • externalId, base or extended

getCustomer

Retrieves a single customer object by its customerId.

Returns a Promise that resolves to a Customer object.

ch.getCustomer(customerId)

getCustomers

Retrieves a paginated list of customers.

Returns a Promise that resolves to a PaginatedResult<Customer> object.

ch.getCustomers(options)

options is an optional object, which can contain one or more of the following properties:

  • externalId

    Only returns customers with this externalId.

  • query

    Only returns customers that match the Custom Query.

  • fields

    An Array that whitelists the fields to retrieve for each customer.

  • sort

    The field where results are ordered.

  • direction

    Either asc (ascending) or desc (descending). Ignored if sort is not specified.

updateCustomer

Updates a customer, removing all their existing properties and replacing them with the ones passed by this method.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.updateCustomer(customerId, customerData)

patchCustomer

Patches a customer, keeping most of their existing properties, while replacing the ones specified in customerData.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.patchCustomer(customerId, customerData)

deleteCustomer

Deletes the customer object with the specified customerId.

Returns a Promise that resolves to true if the customer was successfully deleted.

ch.deleteCustomer(customerId)

Tag API

addTag

Adds a tag to an existing Customer. The new tag will be appended to the tags.manual array of tags, if not already present.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.addTag(customerId, tag)

Warning:

This method can suffer from race conditions, if there are other clients updating the same workspace.

It makes two API calls in short succession, retrieving the existing customer, then patching it to replace the existing array of manual tags. This is temporary workaround, until the API supports atomic updates of the tags.

removeTag

Removes a tag from an existing Customer. The new tag will be removed from the tags.manual array of tags, if present.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.removeTag(customerId, tag)

Warning:

This method can suffer from race conditions, if there are other clients updating the same workspace.

It makes two API calls in short succession, retrieving the existing customer, then patching it to replace the existing array of manual tags. This is temporary workaround, until the API supports atomic updates of the tags.

Education API

addEducation

Adds a new Education object to an existing Customer.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.addEducation(customerId, education)

education is an object with the following properties:

  • id (required)

    A unique identifier for this Education.

  • schoolType

  • schoolName

  • schoolConcentration

  • startYear

  • endYear

  • isCurrent

updateEducation

Updates an existing Education object for an existing Customer.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.updateEducation(customerId, education)

The education object must contain an id that matches an existing Education for the Customer. All the other properties of that Education will be replaced by the new ones provided by this method.

removeEducation

Removes an existing Education object from an existing Customer.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.removeEducation(customerId, educationId)

Job API

addJob

Adds a new Job object to an existing Customer.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.addJob(customerId, job)

job is an object with the following properties:

  • id (required)

    A unique identifier for this Job.

  • companyIndustry

  • companyName

  • jobTitle

  • startDate

  • endDate

  • isCurrent

updateJob

Updates an existing Job object for an existing Customer.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.updateJob(customerId, job)

The job object must contain an id that matches an existing Job for the Customer. All the other properties of that Job will be replaced by the new ones provided by this method.

removeJob

Removes an existing Job object from an existing Customer.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.removeJob(customerId, jobId)

Like API

addLike

Adds a new Like object to an existing Customer.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.addLike(customerId, like)

like is an object with the following properties:

  • id (required)

    A unique identifier for this Like.

  • category

  • name

  • createdTime

updateLike

Updates an existing Like object for an existing Customer.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.updateLike(customerId, like)

The like object must contain an id that matches an existing Like for the Customer. All the other properties of that Like will be replaced by the new ones provided by this method.

removeLike

Removes an existing Like object from an existing Customer.

Returns a Promise that resolves to a Customer object, which contains the updated version of the Customer.

ch.removeLike(customerId, likeId)

Paginated Result

A PaginatedResult object is returned whenever the API returns a paginated list of elements. The page.prev and page.next are utility methods to fetch the adjacent pages.

{
  page: {
    current: number,
    prev: Promise<PaginatedResult<T>>,
    next: Promise<PaginatedResult<T>>,
    total: number
  },
  elements: Array<T>
}

Error Handling

Errors from API are serialized as it follows to be consistent among them:

{
  status: 401,
  message: "The client is not authorized to access the API",
  raw: { ... } // The axios error object
}

You can handle these errors using .catch().

ch.getCustomer(customer.id)
  .then(customer => ch.addLike(customer.id, like))
  .catch((err) => {
    console.log(err.message);
    if (err.status === 401) {
      console.log('Check the validity of your token');
    }
  });

Custom queries

Contacthub supports a complex query language for advanced searches in the Customer list.

Example:

The following is an example of a valid query:

ch.getCustomers({
  query: {
    name: 'testQuery',
    query: {
      name: 'mario',
      type: 'simple',
      are: {
        condition: {
          type: 'atomic',
          attribute: 'base.firstName',
          operator: 'EQUALS',
          value: 'Mario'
        }
      }
    }
  }
});

Query Builder

The QueryBuilder utility class provides apis to create simple and combined queries.

import QueryBuilder, {
  SimpleQuery,
  CombinedQuery,
  AtomicCondition,
  CompositeCondition
} from 'contacthub-sdk-nodejs/QueryBuilder';

const nameQuery = new SimpleQuery()
  .condition(
    new CompositeCondition()
      .conjunction('or')
      .addCondition(new AtomicCondition('base.firstName', 'IS_NOT_NULL'))
      .addCondition(new AtomicCondition('base.lastName', 'EQUALS', 'Rossi'))
      .build()
  )
  .build();

const emailWithExample = new SimpleQuery()
  .condition(new AtomicCondition('base.contacts.email', 'IN', '@example.com'))
  .build();

const  query = new QueryBuilder()
  .combinedQuery(
    new combinedQuery()
      .conjunction('INTERSECT')
      .addQuery(nameQuery)
      .addQuery(emailWithExample)
      .build()
  )
  .build();

The createQuery method from ContactHub class is for creating simple query with an AtomicCondition.

const query = ch.createQuery('base.firstName', 'IS_NOT_NULL');

See the Contacthub documentation for further details.

Examples

Check the example folder for a simple app example.

Contributing to this library

Running tests

Run unit tests with npm test, or npm run test-watch, to enable watch mode.

Run e2e tests with npm run e2e, or npm run e2e-watch' to enable watch mode.

Note:

To run an e2e test, you need to be authenticated with the API. Insert a valid workspaceId, nodeId and token in the environment variables:

export CONTACTHUB_TEST_TOKEN="..."
export CONTACTHUB_TEST_WORKSPACE_ID="..."
export CONTACTHUB_TEST_NODE_ID="..."

Important:

Do NOT use a production workspace, because the tests will write test data (fake Customers and Events) to the workspace they are using.

Flow types

This library uses Flow as a static type checker. Run npm run flow to check the entire project for errors.

Minimum Node version

This SDK is developed and tested against Node.js v6. To help developing against this specific version, we provide a Dockerfile for testing purposes.

Here are the commands to run tests with docker:

$ docker build -t ch-node6 .
$ docker run --rm ch-node6