Skip to content

Adding retrack destination function example #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ this repo as the set of examples.
- [Slack](./destinations/slack) - Adds a Gravatar icon to events with an email and sends messages to Slack
- [Zendesk](./destinations/zendesk) - Create new Zendesk tickets triggered by events that you send
- [Datadog](./destinations/datadog) - Sends a metric to datadog with high level message/event type as tags
- [Optimizely](./destinations/optimizely) - Sends conversion metrix to optimizely.
- [Optimizely](./destinations/optimizely) - Sends conversion metrix to optimizely
- [Retrack](./destinations/retrack) - Intercepts track event, updates user identity and enriches said event

## Development

Expand Down
11 changes: 11 additions & 0 deletions destinations/retrack/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Re-track Custom Destination Function

Example of destination function which:
* Intercepts track event from Segment source attached to it,
* modifies userId and posts [alias](https://segment.com/docs/connections/spec/alias/) request, so Segment will know anticipated identity,
* enriches event properties and posts [track](https://segment.com/docs/connections/spec/track/) request, so Segment will know enriched event,
* all requests are being forwarded to another [Segment HTTP Tracking API Source](https://segment.com/docs/connections/sources/catalog/libraries/server/http-api/), given `apiKey` from function settings.

## Settings

- `apiKey` {String} ([write key of Segment HTTP Tracking API Source](https://segment.com/docs/connections/sources/catalog/libraries/server/http-api/))
81 changes: 81 additions & 0 deletions destinations/retrack/handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* @typedef {Object} SegmentTrackEvent
* @see {@link https://segment.com/docs/connections/spec/track/} for full track event spec
* @see {@link https://segment.com/docs/connections/spec/common/} for full common fields spec
* @property {String} event Track event name
* @property {String} messageId Original API message identifier
* @property {String} userId Tracked user id that we want to modify and re-track
* @property {String} timestamp Timestamp of event in ISO 8601 format
* @property {Object} properties Track event arbitrary properties, we want to add 3 own
*/

/**
* @typedef {Object} FunctionSettings
* @property {String} apiKey Write key of source to forward alias and track events to
*/

/**
* Call Segment V1 API, using HTTP API Segment Source by write key
* @see {@link https://segment.com/docs/connections/sources/catalog/libraries/server/http-api/} for source doc
* @internal
* @param {String} apiKey
* @param {String<'alias'|'track'>} route
* @param {Object} body
* @return {Promise<void>}
*/
async function callSegmentAPI(apiKey, route, body) {
let response;

try {
response = await fetch(`https://api.segment.io/v1/${route}`, {
method: 'POST',
headers: {
Authorization: `Basic ${btoa(`${apiKey}:`)}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
} catch (error) {
throw new RetryError(error.message);
}

if (response.status >= 500 || response.status === 429) {
throw new RetryError(`Failed with ${response.status}`);
}
}

/**
* Handle track event
* @param {SegmentTrackEvent} event
* @param {FunctionSettings} settings
* @return {Promise<void>}
*/
async function onTrack(event, settings) {
const { apiKey } = settings;

if (!apiKey) {
throw new ValidationError('Forward source write key is required');
}

const anticipatedId = crypto.createHash('md5').update(event.userId).digest('hex');

const [slug1, slug2, slug3] = event.userId.split('-');

await Promise.all([
callSegmentAPI(apiKey, 'alias', {
previousId: event.userId,
userId: anticipatedId,
timestamp: event.timestamp,
}),
callSegmentAPI(apiKey, 'track', {
event: event.event,
userId: anticipatedId,
properties: {
...event.properties,
slug1,
slug2,
slug3,
},
}),
]);
}