Skip to content

Commit

Permalink
adding sift custom destination function (#34)
Browse files Browse the repository at this point in the history
* First sift push

* update readme + prettier handler

* Add Sift Decisions, WF, and update function names.

* added changes

* Added support for multiple sift response types

Co-authored-by: Ju Hae Lee <[email protected]>
Co-authored-by: Sophie Saouma <[email protected]>
  • Loading branch information
3 people authored Mar 16, 2021
1 parent 3758d7c commit 72c80c8
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 0 deletions.
19 changes: 19 additions & 0 deletions destinations/sift/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Sift Custom Destination Function
This example shows how to set up a custom destination function with [Sift](https://sift.com/), a solution that helps you prevent all types of online fraud and abuse. The destination not only sends events to Sift, but also takes the results from Sift and attaches the metric to a user's profile using the `identify` call.

## Setup
- [ ] Create a [HTTP Source](https://segment.com/docs/connections/sources/catalog/libraries/server/http-api/#http%20tracking%20api)
- [ ] Grab the REST API Key from Sift in your account

## How to use

Copy the `handler.js` code in this directory to your destination function

Make the necessary modifications in the `handler.js` to map your Segment data.

Replace the first line with your Segment write key that you generated from creating an HTTP Source

## Maintainers
[@shyaankhan](https://github.com/shyaankhan) Segment
[@ssaouma](https://github.com/ssaouma) Sift
[@juhaelee](https://github.com/juhaelee) Segment
145 changes: 145 additions & 0 deletions destinations/sift/handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Segment & Sift
const SEGMENT_WRITE_KEY = '';
const siftEndpoint = 'https://api.sift.com/v205/events';
const endpointScore = siftEndpoint + '?return_score=true';
const endpointWorkflow = siftEndpoint + '?return_workflow_status=true';

async function addScores(fields, res) {
if (res.status == 0) {
var scoreBody = {
userId: fields.$user_id,
traits: {
contentAbuseScore: res.score_response.scores.content_abuse.score,
paymentAbuseScore: res.score_response.scores.payment_abuse.score
}
};

const request = await fetch('https://api.segment.io/v1/identify', {
body: JSON.stringify(scoreBody),
headers: new Headers({
Authorization: 'Basic ' + btoa(SEGMENT_WRITE_KEY + ':'),
'Content-Type': 'application/json'
}),
method: 'post'
});

return request.json();
}
}

async function addDecisions(fields, res) {
var decisionBody = {
userId: fields.$user_id,
traits: {
contentAbuseDecisions:
res.score_response.workflow_statuses[0].history[0].config.decision_id,
paymentAbuseDecisions:
res.score_response.workflow_statuses[0].history[0].config.decision_id
}
};

const request = await fetch('https://api.segment.io/v1/identify', {
body: JSON.stringify(decisionBody),
headers: new Headers({
Authorization: 'Basic ' + btoa(SEGMENT_WRITE_KEY + ':'),
'Content-Type': 'application/json'
}),
method: 'post'
});

return request.json();
}

function getUrl(type) {
if (type == 'SCORE') {
return endpointScore;
} else if (type == 'WORKFLOW') {
return endpointWorkflow;
} else {
return siftEndpoint;
}
}

async function siftEventCall(fields, type) {
const res = await fetch(getUrl(type), {
body: JSON.stringify(fields),
headers: { 'Content-Type': 'application/json' },
method: 'post'
});

const siftResponse = await res.json();

if (siftResponse.status <= 0) {
// Please implement conditions for retries.
} else if (siftResponse.status >= 0) {
throw new InvalidEventPayload(siftResponse.error_message);
}

var response;

if (type == 'SCORE') {
response = await addScores(fields, siftResponse);
} else if (type == 'WORKFLOW') {
response = await addDecisions(fields, siftResponse);
}

return response;
}

async function onTrack(event, settings) {
var fields = {};
// Depending on when you want to call for a score, set the appropriate endpoint to hit.
if (event.event == 'Signed Up') {
fields = {
$type: '$create_account',
$user_id: event.userId,
$name: event.properties.name,
$user_email: event.properties.email,
$ip: event.context.ip,
$phone: event.properties.phone,
$browser: {
$user_agent: event.context.userAgent
},
$api_key: settings.apiKey
};

return siftEventCall(fields, 'REGULAR');
} else if (event.event == 'Signed In') {
fields = {
$type: '$login',
$login_status: '$success',
$user_id: event.userId,
$username: event.properties.username,
$ip: event.context.ip,
$browser: {
$user_agent: event.context.userAgent
},
$api_key: settings.apiKey
};

return siftEventCall(fields, 'REGULAR');
} else {
return null;
}
}

async function onIdentify(event, settings) {
// Depending on when you want to call for a score, set the appropriate endpoint to hit.

if (!event.userId) return;

var fields = {
$type: '$update_account',
$user_id: event.userId,
$name: event.traits.name,
$user_email: event.traits.email,
$ip: event.context.ip,
$phone: event.traits.phone,
$browser: {
$user_agent: event.context.userAgent
},
$api_key: settings.apiKey
};

return siftEventCall(fields, endpoint);
}

0 comments on commit 72c80c8

Please sign in to comment.