Skip to content

Commit

Permalink
Adding new kevel-audience Destination (#1910)
Browse files Browse the repository at this point in the history
* adding kevel-audience Destination

* fixing spelling issue
  • Loading branch information
joe-ayoub-segment authored Mar 5, 2024
1 parent ca71fbf commit 726d281
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 5 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type { DestinationDefinition } from '@segment/actions-core'
import type { Settings } from './generated-types'

import syncKevelAudience from './syncKevelAudience'

const destination: DestinationDefinition<Settings> = {
name: 'Kevel Audience (Actions)',
slug: 'actions-kevel-audience',
description:
'Sync Segment user profile traits and Engage Audiences to Kevel Audiences. Only users with a Segment userId will be synced.',
mode: 'cloud',

authentication: {
scheme: 'custom',
fields: {
audienceDomain: {
label: 'Kevel Audience Domain',
description: 'Your Kevel Audience root subdomain. For example: "cdp.yourdomain.com".',
type: 'string',
required: true
},
userIdType: {
label: 'Kevel Audience User ID Type',
description: 'Kevel Audience User ID Type to map your Segment User ID to. For example: "crm".',
type: 'string',
required: true
},
clientId: {
label: 'Kevel Audience client ID',
description: 'The Kevel Audience client ID to identify the event. For example: "brand-name".',
type: 'string',
required: true
},
siteId: {
label: 'Kevel Audience site ID',
description: 'The Kevel Audience site ID to identify the event. For example: "segment-app".',
type: 'string',
required: true
},
apiKey: {
label: 'Kevel Audience API Key',
description:
'The Kevel Audience API Key to authorize the requests. Get yours from your Kevel Customer Success representative.',
type: 'string',
required: true
},
eventType: {
label: 'Event Type',
description: 'The type of event to send to Kevel Audience. For example: "segmentSync".',
type: 'string',
required: true
}
}
},
extendRequest() {
return {
headers: {
'Content-Type': 'application/json'
}
}
},
actions: {
syncKevelAudience
}
}

export default destination
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import nock from 'nock'
import { createTestEvent, createTestIntegration } from '@segment/actions-core'
import Destination from '../../index'

const testDestination = createTestIntegration(Destination)

const goodTrackEvent = createTestEvent({
type: 'track',
userId: 'uid1',
context: {
personas: {
computation_class: 'audience',
computation_key: 'kevel_segment_test_name'
},
traits: {
email: 'test@email.com'
}
},
properties: {
audience_key: 'kevel_segment_test_name',
kevel_segment_test_name: true
}
})

const goodIdentifyEvent = createTestEvent({
type: 'identify',
userId: 'uid1',
context: {
personas: {
computation_class: 'audience',
computation_key: 'kevel_segment_test_name'
}
},
traits: {
audience_key: 'kevel_segment_test_name',
kevel_segment_test_name: true
},
properties: undefined
})

describe('KevelAuddience.syncKevelAudience', () => {
it('should not throw an error if the audience creation succeed - track', async () => {
const baseUrl = 'https://tr.domain.brand.com/'

nock(baseUrl)
.post('/events/server', (body) => body.customData.kevel_segment_test_name === true)
.reply(200)

await expect(
testDestination.testAction('syncKevelAudience', {
event: goodTrackEvent,
settings: {
audienceDomain: 'domain.brand.com',
userIdType: 'email_sha256',
apiKey: 'api_key',
clientId: 'client_id',
siteId: 'site_id',
eventType: 'segmentSync'
},
useDefaultMappings: true
})
).resolves.not.toThrowError()
})

it('should not throw an error if the audience creation succeed - identify', async () => {
const baseUrl = 'https://tr.domain.brand.com'

nock(baseUrl)
.post('/events/server', (body) => body.customData.kevel_segment_test_name === true)
.reply(200)

await expect(
testDestination.testAction('syncKevelAudience', {
event: goodIdentifyEvent,
settings: {
audienceDomain: 'domain.brand.com',
userIdType: 'email_sha256',
apiKey: 'api_key',
clientId: 'client_id',
siteId: 'site_id',
eventType: 'segmentSync'
},
useDefaultMappings: true
})
).resolves.not.toThrowError()
})
})

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { ActionDefinition } from '@segment/actions-core'
import type { Settings } from '../generated-types'
import type { Payload } from './generated-types'

const action: ActionDefinition<Settings, Payload> = {
title: 'Sync Kevel Audience',
description:
'Sync Segment user profile traits and Engage Audiences to Kevel Audiences. Only users with a Segment userId will be synced.',
defaultSubscription: 'type = "track" or type = "identify"',
fields: {
segment_user_id: {
label: 'User ID',
description: "The user's unique ID",
type: 'string',
unsafe_hidden: true,
required: true,
default: { '@path': '$.userId' }
},
traits_or_props: {
label: 'Traits or properties object',
description: 'A computed object for track and identify events. This field should not need to be edited.',
type: 'object',
required: true,
unsafe_hidden: true,
default: {
'@if': {
exists: { '@path': '$.properties' },
then: { '@path': '$.properties' },
else: { '@path': '$.traits' }
}
}
}
},
perform: async (request, data) => {
const baseUrl = `https://tr.${data.settings.audienceDomain}/events/server` // TODO event tracker
const payload = {
clientId: data.settings.clientId,
siteId: data.settings.siteId,
type: 'custom',
customType: data.settings.eventType,
user: {
type: data.settings.userIdType,
id: data.payload.segment_user_id
},
customData: data.payload.traits_or_props
}

return request(`${baseUrl}`, {
json: payload,
method: 'POST'
})
}
}

export default action
4 changes: 2 additions & 2 deletions packages/destination-actions/src/destinations/kevel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import syncAudience from './syncAudience'
import syncTraits from './syncTraits'

const destination: DestinationDefinition<Settings> = {
name: 'Kevel (Actions)',
name: 'Kevel UserDB (Actions)',
slug: 'actions-kevel',
description:
'Send Segment user profiles and Segment Audiences to Kevel. Only users with a Segment userId will be synced.',
'Send Segment user profiles and Audiences to Kevel UserDB for campaign targeting. Only users with a Segment userId will be synced.',
mode: 'cloud',

authentication: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ describe('Kevel.syncAudience', () => {
).resolves.not.toThrowError()
})

it('should not throw an error if the audience creation succeed - track', async () => {
it('should not throw an error if the audience creation succeed - identify', async () => {
const userId = 'uid1'
const networkId1 = 'networkId1'
const baseUrl = `https://e-${networkId1}.adzerk.net/udb/${networkId1}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import type { Payload } from './generated-types'

const action: ActionDefinition<Settings, Payload> = {
title: 'Sync Audience',
description: 'Sync a Segment Engage Audience to a Kevel Segment. Only users with a Segment userId will be synced.',
description:
"Sync a Segment Engage Audience to a Kevel UserDB Interest. Only users with a Segment userId will be synced. See Kevel's [documentation for more details](https://dev.kevel.com/reference/add-interest-to-user).",
defaultSubscription: 'type = "track" or type = "identify"',
fields: {
segment_computation_key: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import type { Payload } from './generated-types'

const action: ActionDefinition<Settings, Payload> = {
title: 'Sync Traits',
description: 'Sync user profile traits from Segment to Kevel',
description:
"Sync user profile traits and Audiences from Segment to Kevel UserDB as `customProperties`. See Kevel's [documentation for more details](https://dev.kevel.com/reference/set-custom-properties-alternative).",
defaultSubscription: 'type = "identify"',
fields: {
segment_user_id: {
Expand Down

0 comments on commit 726d281

Please sign in to comment.