Add Customer.io-Node (#833)

* 🚧 Descriptions, node function, generic function changes

*  Finished functionality, added icon

*  Added new campaign operations, acommodated for 2 different authentications

*  Fixed number defaults not being numbers but empty strings
This commit is contained in:
Rupenieks 2020-09-02 12:25:11 +02:00 committed by GitHub
parent 0e1a4e5309
commit e5a5e1ed11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 1301 additions and 12 deletions

View file

@ -10,11 +10,26 @@ export class CustomerIoApi implements ICredentialType {
documentationUrl = 'customerIo';
properties = [
{
displayName: 'App API Key',
name: 'apiKey',
displayName: 'Tracking API Key',
name: 'trackingApiKey',
type: 'string' as NodePropertyTypes,
default: '',
description: 'Required for tracking API.',
required: true
},
{
displayName: 'Tracking Site ID',
name: 'trackingSiteId',
type: 'string' as NodePropertyTypes,
default: '',
description: 'Required for tracking API.'
},
{
displayName: 'App API Key',
name: 'appApiKey',
type: 'string' as NodePropertyTypes,
default: '',
description: 'Required for App API.'
},
];
}

View file

@ -0,0 +1,199 @@
import { INodeProperties } from 'n8n-workflow';
export const campaignOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'campaign',
],
},
},
options: [
{
name: 'Get',
value: 'get',
},
{
name: 'Get All',
value: 'getAll',
},
{
name: 'Get Metrics',
value: 'getMetrics',
},
],
default: 'get',
description: 'The operation to perform',
},
] as INodeProperties[];
export const campaignFields = [
/* -------------------------------------------------------------------------- */
/* campaign:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'Campaign ID',
name: 'campaignId',
type: 'number',
required: true,
default: 0,
displayOptions: {
show: {
resource: [
'campaign',
],
operation: [
'get'
]
},
},
description: 'The unique identifier for the campaign',
},
/* -------------------------------------------------------------------------- */
/* campaign:getMetrics */
/* -------------------------------------------------------------------------- */
{
displayName: 'Campaign ID',
name: 'campaignId',
type: 'number',
required: true,
default: 0,
displayOptions: {
show: {
resource: [
'campaign',
],
operation: [
'getMetrics'
]
},
},
description: 'The unique identifier for the campaign',
},
{
displayName: 'Period',
name: 'period',
type: 'options',
default: 'days',
displayOptions: {
show: {
resource: [
'campaign',
],
operation: [
'getMetrics'
]
},
},
description: 'Specify metric period',
options: [
{
name: 'Hours',
value: 'hours'
},
{
name: 'Days',
value: 'days'
},
{
name: 'Weeks',
value: 'weeks'
},
{
name: 'Months',
value: 'months'
},
]
},
{
displayName: 'JSON Parameters',
name: 'jsonParameters',
type: 'boolean',
default: false,
description: '',
displayOptions: {
show: {
resource: [
'campaign',
],
operation: [
'getMetrics'
],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'campaign',
],
operation: [
'getMetrics'
],
jsonParameters: [
false,
],
},
},
options: [
{
displayName: 'Steps',
name: 'steps',
type: 'number',
default: 0,
description: 'Integer specifying how many steps to return. Defaults to the maximum number of timeperiods available, or 12 when using the months period. Maximum timeperiods available are 24 hours, 45 days, 12 weeks and 120 months',
typeOptions: {
minValue: 0,
maxValue: 120
}
},
{
displayName: 'Type',
name: 'type',
type: 'options',
default: 'empty',
description: 'Specify metric type',
options: [
{
name: 'Empty',
value: 'empty'
},
{
name: 'Email',
value: 'email'
},
{
name: 'Webhook',
value: 'webhook'
},
{
name: 'twilio',
value: 'twilio'
},
{
name: 'Urban Airship',
value: 'urbanAirship'
},
{
name: 'Slack',
value: 'slack'
},
{
name: 'Push',
value: 'push'
},
]
},
],
},
] as INodeProperties[];

View file

@ -0,0 +1,326 @@
import { INodeProperties } from 'n8n-workflow';
export const customerOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'customer',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a customer.',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a customer.',
},
{
name: 'Update',
value: 'update',
description: 'Update a customer.',
},
],
default: 'create',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const customerFields = [
/* -------------------------------------------------------------------------- */
/* customer:create/delete */
/* -------------------------------------------------------------------------- */
{
displayName: 'ID',
name: 'id',
type: 'number',
required: true,
default: 0,
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'create', 'delete'
]
},
},
description: 'The unique identifier for the customer.',
},
{
displayName: 'Email',
name: 'email',
type: 'string',
default: '',
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'create'
]
},
},
description: 'The email address of the user.',
},
{
displayName: 'Created at',
name: 'createdAt',
type: 'dateTime',
default: '',
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'create'
]
},
},
description: 'The UNIX timestamp from when the user was created.',
},
{
displayName: 'JSON Parameters',
name: 'jsonParameters',
type: 'boolean',
default: false,
description: '',
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'create'
],
},
},
},
{
displayName: ' Additional Fields',
name: 'additionalFieldsJson',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'create'
],
jsonParameters: [
true,
],
},
},
description: 'Object of values to set as described <a href="https://github.com/agilecrm/rest-api#1-companys---companies-api" target="_blank">here</a>.',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'create'
],
jsonParameters: [
false,
],
},
},
options: [
{
displayName: 'Custom Properties',
name: 'customProperties',
type: 'fixedCollection',
description: 'Custom Properties',
typeOptions: {
multipleValues: true,
},
options: [
{
displayName: 'Property',
name: 'customProperty',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
required: true,
default: '',
description: 'Property name.',
placeholder: 'Plan'
},
{
displayName: 'Value',
name: 'value',
type: 'string',
required: true,
default: '',
description: 'Property value.',
placeholder: 'Basic'
},
],
},
]
},
],
},
/* -------------------------------------------------------------------------- */
/* customer:update */
/* -------------------------------------------------------------------------- */
{
displayName: 'ID',
name: 'id',
type: 'number',
required: true,
default: 0,
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'update'
]
},
},
description: 'The unique identifier for the customer.',
},
{
displayName: 'JSON Parameters',
name: 'jsonParameters',
type: 'boolean',
default: false,
description: '',
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'update'
],
},
},
},
{
displayName: ' Additional Fields',
name: 'additionalFieldsJson',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'update'
],
jsonParameters: [
true,
],
},
},
description: 'Object of values to set as described <a href="https://github.com/agilecrm/rest-api#1-companys---companies-api" target="_blank">here</a>.',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'customer',
],
operation: [
'update'
],
jsonParameters: [
false,
],
},
},
options: [
{
displayName: 'Custom Properties',
name: 'customProperties',
type: 'fixedCollection',
description: 'Custom Properties',
typeOptions: {
multipleValues: true,
},
options: [
{
displayName: 'Property',
name: 'customProperty',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
required: true,
default: '',
description: 'Property name.',
placeholder: 'Plan'
},
{
displayName: 'Value',
name: 'value',
type: 'string',
required: true,
default: '',
description: 'Property value.',
placeholder: 'Basic'
},
],
},
]
},
{
displayName: 'Email',
name: 'email',
type: 'string',
default: '',
description: 'The email address of the user.',
},
{
displayName: 'Created at',
name: 'createdAt',
type: 'dateTime',
default: '',
description: 'The UNIX timestamp from when the user was created.',
},
],
},
] as INodeProperties[];

View file

@ -0,0 +1,359 @@
import {
IExecuteFunctions,
} from 'n8n-core';
import {
IDataObject,
INodeTypeDescription,
INodeExecutionData,
INodeType,
ILoadOptionsFunctions,
INodePropertyOptions,
} from 'n8n-workflow';
import { customerIoApiRequest, validateJSON } from './GenericFunctions';
import { campaignOperations, campaignFields } from './CampaignDescription';
import { customerOperations, customerFields } from './CustomerDescription';
import { eventOperations, eventFields } from './EventDescription';
import { segmentOperations, segmentFields } from './SegmentDescription';
import { DateTime } from '../DateTime.node';
export class CustomerIo implements INodeType {
description: INodeTypeDescription = {
displayName: 'Customer.io',
name: 'customerio',
icon: 'file:customerio.png',
group: ['output'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume Customer.io API',
defaults: {
name: 'CustomerIo',
color: '#ffcd00',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'customerIoApi',
required: true,
}
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
options: [
{
name: 'Customer',
value: 'customer',
},
{
name: 'Event',
value: 'event',
},
{
name: 'Campaign',
value: 'campaign',
},
{
name: 'Segment',
value: 'segment',
},
],
default: 'customer',
description: 'Resource to consume.',
},
// CAMPAIGN
...campaignOperations,
...campaignFields,
// CUSTOMER
...customerOperations,
...customerFields,
// EVENT
...eventOperations,
...eventFields,
// SEGMENT
...segmentOperations,
...segmentFields
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const returnData: IDataObject[] = [];
const items = this.getInputData();
let responseData;
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
const body : IDataObject = {};
for (let i = 0; i < items.length; i++) {
if (resource === 'campaign') {
if (operation === 'get') {
const campaignId = this.getNodeParameter('campaignId', i) as number;
const endpoint = `/campaigns/${campaignId}`;
responseData = await customerIoApiRequest.call(this, 'GET', endpoint, body, 'beta');
}
if (operation === 'getAll') {
const endpoint = `/campaigns`;
responseData = await customerIoApiRequest.call(this, 'GET', endpoint, body, 'beta');
responseData = responseData.campaigns;
}
if (operation === 'getMetrics') {
const campaignId = this.getNodeParameter('campaignId', i) as number;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new Error('Additional fields must be a valid JSON');
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const period = this.getNodeParameter('period', i) as string;
let endpoint = `/campaigns/${campaignId}/metrics`;
if (period !== 'days') {
endpoint = `${endpoint}?period=${period}`;
}
if (additionalFields.steps) {
body.steps = additionalFields.steps as number;
}
if (additionalFields.type) {
if (additionalFields.type === 'urbanAirship') {
additionalFields.type = 'urban_airship';
} else {
body.type = additionalFields.type as string;
}
}
responseData = await customerIoApiRequest.call(this, 'GET', endpoint, body, 'beta');
responseData = responseData.metric;
}
}
}
if (resource === 'customer') {
if (operation === 'create') {
const id = this.getNodeParameter('id', i) as number;
const email = this.getNodeParameter('email', i) as string;
const createdAt = this.getNodeParameter('createdAt', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
body.email = email;
body.created_at = new Date(createdAt).getTime() / 1000;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new Error('Additional fields must be a valid JSON');
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.customProperties) {
const data : any = {};
//@ts-ignore
additionalFields.customProperties.customProperty.map(property => {
data[property.key] = property.value;
});
body.data = data;
}
}
const endpoint = `/customers/${id}`;
responseData = await customerIoApiRequest.call(this, 'PUT', endpoint, body, 'tracking');
}
if (operation === 'update') {
const id = this.getNodeParameter('id', i) as number;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new Error('Additional fields must be a valid JSON');
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.customProperties) {
const data : any = {};
//@ts-ignore
additionalFields.customProperties.customProperty.map(property => {
data[property.key] = property.value;
});
body.data = data;
}
if (additionalFields.email) {
body.email = additionalFields.email as string;
}
if (additionalFields.createdAt) {
body.created_at = new Date(additionalFields.createdAt as string).getTime() / 1000;
}
}
const endpoint = `/customers/${id}`;
responseData = await customerIoApiRequest.call(this, 'PUT', endpoint, body, 'tracking');
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', i) as number;
body.id = id;
const endpoint = `/customers/${id}`;
responseData = await customerIoApiRequest.call(this, 'DELETE', endpoint, body, 'tracking');
}
}
if (resource === 'event') {
if (operation === 'track') {
const id = this.getNodeParameter('id', i) as number;
const name = this.getNodeParameter('name', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
body.name = name;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new Error('Additional fields must be a valid JSON');
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const data : any = {};
if (additionalFields.customAttributes) {
//@ts-ignore
additionalFields.customAttributes.customAttribute.map(property => {
data[property.key] = property.value;
});
}
if (additionalFields.type) {
data.type = additionalFields.type as string;
}
body.data = data;
}
const endpoint = `/customers/${id}/events`;
responseData = await customerIoApiRequest.call(this, 'POST', endpoint, body, 'tracking');
}
if (operation === 'trackAnonymous') {
const name = this.getNodeParameter('name', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
body.name = name;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new Error('Additional fields must be a valid JSON');
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const data : any = {};
if (additionalFields.customAttributes) {
//@ts-ignore
additionalFields.customAttributes.customAttribute.map(property => {
data[property.key] = property.value;
});
}
body.data = data;
}
const endpoint = `/events`;
responseData = await customerIoApiRequest.call(this, 'POST', endpoint, body, 'tracking');
}
}
if (resource === 'segment') {
const id = this.getNodeParameter('id', i) as number;
const ids = this.getNodeParameter('ids', i) as string;
const idArray : string[] = [];
ids.split(',').map(id => {
idArray.push(id);
});
body.id = id;
body.ids = idArray;
let endpoint = ``;
if (operation === 'add') {
endpoint = `/segments/${id}/add_customers`;
} else {
endpoint = `/segments/${id}/remove_customers`;
}
responseData = await customerIoApiRequest.call(this, 'POST', endpoint, body, 'tracking');
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as unknown as IDataObject);
}
}
return [this.helpers.returnJsonArray(returnData)];
}
}

View file

@ -11,7 +11,7 @@ import {
} from 'n8n-workflow';
import {
apiRequest,
customerIoApiRequest,
eventExists,
} from './GenericFunctions';
@ -34,7 +34,7 @@ export class CustomerIoTrigger implements INodeType {
description: 'Starts the workflow on a Customer.io update. (Beta)',
defaults: {
name: 'Customer.io Trigger',
color: '#7131ff',
color: '#ffcd00',
},
inputs: [],
outputs: ['main'],
@ -237,7 +237,7 @@ export class CustomerIoTrigger implements INodeType {
const endpoint = '/reporting_webhooks';
let { reporting_webhooks: webhooks } = await apiRequest.call(this, 'GET', endpoint, {});
let { reporting_webhooks: webhooks } = await customerIoApiRequest.call(this, 'GET', endpoint, {}, 'beta');
if (webhooks === null) {
webhooks = [];
@ -295,7 +295,7 @@ export class CustomerIoTrigger implements INodeType {
events: data,
};
webhook = await apiRequest.call(this, 'POST', endpoint, body);
webhook = await customerIoApiRequest.call(this, 'POST', endpoint, body, 'beta');
const webhookData = this.getWorkflowStaticData('node');
webhookData.webhookId = webhook.id as string;
@ -307,7 +307,7 @@ export class CustomerIoTrigger implements INodeType {
if (webhookData.webhookId !== undefined) {
const endpoint = `/reporting_webhooks/${webhookData.webhookId}`;
try {
await apiRequest.call(this, 'DELETE', endpoint, {});
await customerIoApiRequest.call(this, 'DELETE', endpoint, {}, 'beta');
} catch (e) {
return false;
}

View file

@ -0,0 +1,296 @@
import { INodeProperties } from 'n8n-workflow';
export const eventOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'event',
],
},
},
options: [
{
name: 'Track',
value: 'track',
description: 'Track a customer event.',
},
{
name: 'Track Anonymous',
value: 'trackAnonymous',
description: 'Track an anonymous event.',
},
],
default: 'track',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const eventFields = [
/* -------------------------------------------------------------------------- */
/* event:track */
/* -------------------------------------------------------------------------- */
{
displayName: 'ID',
name: 'id',
type: 'number',
required: true,
default: 0,
displayOptions: {
show: {
resource: [
'event',
],
operation: [
'track'
]
},
},
description: 'The unique identifier for the customer.',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
displayOptions: {
show: {
resource: [
'event',
],
operation: [
'track'
]
},
},
description: 'Name of the event to track.',
},
{
displayName: 'JSON Parameters',
name: 'jsonParameters',
type: 'boolean',
default: false,
description: '',
displayOptions: {
show: {
resource: [
'event',
],
operation: [
'track'
],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFieldsJson',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
displayOptions: {
show: {
resource: [
'event',
],
operation: [
'track'
],
jsonParameters: [
true,
],
},
},
description: 'Object of values to set as described <a href="https://customer.io/docs/api-triggered-data-format#basic-data-formatting" target="_blank">here</a>.',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'event',
],
operation: [
'track'
],
jsonParameters: [
false
]
},
},
options: [
{
displayName: 'Custom Attributes',
name: 'customAttributes',
type: 'fixedCollection',
description: 'Custom Properties',
typeOptions: {
multipleValues: true,
},
options: [
{
displayName: 'Attribute',
name: 'customAttribute',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
required: true,
default: '',
description: 'Attribute name.',
placeholder: 'Price'
},
{
displayName: 'Value',
name: 'value',
type: 'string',
required: true,
default: '',
description: 'Attribute value.',
placeholder: '25.50'
},
],
},
]
},
{
displayName: 'Type',
name: 'type',
type: 'string',
default: '',
description: 'Used to change event type. For Page View events set to "page".',
},
],
},
/* -------------------------------------------------------------------------- */
/* event:track anonymous */
/* -------------------------------------------------------------------------- */
{
displayName: 'Name',
name: 'name',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'event',
],
operation: [
'trackAnonymous'
]
},
},
description: 'The unique identifier for the customer.',
},
{
displayName: 'JSON Parameters',
name: 'jsonParameters',
type: 'boolean',
default: false,
description: '',
displayOptions: {
show: {
resource: [
'event',
],
operation: [
'trackAnonymous'
],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFieldsJson',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
displayOptions: {
show: {
resource: [
'event',
],
operation: [
'trackAnonymous'
],
jsonParameters: [
true,
],
},
},
description: 'Object of values to set as described <a href="https://customer.io/docs/api-triggered-data-format#basic-data-formatting" target="_blank">here</a>.',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'event',
],
operation: [
'trackAnonymous'
],
jsonParameters: [
false
]
},
},
options: [
{
displayName: 'Custom Attributes',
name: 'customAttributes',
type: 'fixedCollection',
description: 'Custom Properties',
typeOptions: {
multipleValues: true,
},
options: [
{
displayName: 'Attribute',
name: 'customAttribute',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
required: true,
default: '',
description: 'Attribute name.',
placeholder: 'Price'
},
{
displayName: 'Value',
name: 'value',
type: 'string',
required: true,
default: '',
description: 'Attribute value.',
placeholder: '25.50'
},
],
},
]
},
],
},
] as INodeProperties[];

View file

@ -16,7 +16,7 @@ import {
get,
} from 'lodash';
export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: object, query?: IDataObject): Promise<any> { // tslint:disable-line:no-any
export async function customerIoApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: object, baseApi? : string, query?: IDataObject): Promise<any> { // tslint:disable-line:no-any
const credentials = this.getCredentials('customerIoApi');
if (credentials === undefined) {
@ -28,14 +28,26 @@ export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoa
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${credentials.apiKey}`,
},
method,
body,
qs: query,
uri: `https://beta-api.customer.io/v1/api${endpoint}`,
uri: '',
json: true,
};
if (baseApi === 'tracking') {
options.uri = `https://track.customer.io/api/v1${endpoint}`;
const basicAuthKey = Buffer.from(`${credentials.trackingSiteId}:${credentials.trackingApiKey}`).toString('base64');
Object.assign(options.headers, {'Authorization': `Basic ${basicAuthKey}`});
} else if (baseApi === 'api') {
options.uri = `https://api.customer.io/v1/api${endpoint}`;
const basicAuthKey = Buffer.from(`${credentials.trackingSiteId}:${credentials.trackingApiKey}`).toString('base64');
Object.assign(options.headers, {'Authorization': `Basic ${basicAuthKey}`});
} else if (baseApi === 'beta') {
options.uri = `https://beta-api.customer.io/v1/api${endpoint}`;
Object.assign(options.headers, {'Authorization': `Bearer ${credentials.appApiKey as string}`});
}
try {
return await this.helpers.request!(options);
} catch (error) {
@ -63,3 +75,13 @@ export function eventExists(currentEvents: string[], webhookEvents: IDataObject)
}
return true;
}
export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any
let result;
try {
result = JSON.parse(json!);
} catch (exception) {
result = undefined;
}
return result;
}

View file

@ -0,0 +1,71 @@
import { INodeProperties } from 'n8n-workflow';
export const segmentOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'segment',
],
},
},
options: [
{
name: 'Add Customer',
value: 'add',
},
{
name: 'Remove Customer',
value: 'remove',
},
],
default: 'add',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const segmentFields = [
/* -------------------------------------------------------------------------- */
/* segment:add */
/* -------------------------------------------------------------------------- */
{
displayName: 'ID',
name: 'id',
type: 'number',
required: true,
default: 0,
displayOptions: {
show: {
resource: [
'segment',
],
operation: [
'add', 'remove'
]
},
},
description: 'The unique identifier of the segment.',
},
{
displayName: 'IDs',
name: 'ids',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'segment',
],
operation: [
'add', 'remove'
]
},
},
description: 'A list of customer ids to add to the segment.',
},
] as INodeProperties[];

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -217,6 +217,7 @@
"dist/nodes/CrateDb/CrateDb.node.js",
"dist/nodes/Cron.node.js",
"dist/nodes/Crypto.node.js",
"dist/nodes/CustomerIo/CustomerIo.node.js",
"dist/nodes/CustomerIo/CustomerIoTrigger.node.js",
"dist/nodes/DateTime.node.js",
"dist/nodes/Discord/Discord.node.js",