Skip to content

Commit 521a9fc

Browse files
[Snap Audiences] - Snap Audience Destination (#3339)
* Started work on snap audience rewrite * progress * progress * adding tests * updating types
1 parent 9749125 commit 521a9fc

File tree

13 files changed

+572
-798
lines changed

13 files changed

+572
-798
lines changed

packages/destination-actions/src/destinations/snap-audiences/__tests__/index.test.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ describe('Snap Audiences', () => {
3030
.post(`/v1/adaccounts/${ad_account_id}/segments`, {
3131
segments: [
3232
{
33-
name: 'Custom Name',
34-
source_type: 'FIRST_PARTY',
35-
ad_account_id: ad_account_id,
36-
description: '',
33+
name: "Custom Name",
34+
source_type: "FIRST_PARTY",
35+
ad_account_id: "22222222",
36+
description: "Audience Snap Audience Name created by Segment",
3737
retention_in_days: 9999
3838
}
3939
]
@@ -54,7 +54,4 @@ describe('Snap Audiences', () => {
5454
expect(res).toEqual({ externalId: audienceId })
5555
})
5656
})
57-
58-
// describe('getAudience', () => {
59-
// })
6057
})
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const ACCESS_TOKEN_URL = 'https://accounts.snapchat.com/login/oauth2/access_token'
2+
3+
export const DEFAULT_RETENTION_DAYS = 9999

packages/destination-actions/src/destinations/snap-audiences/generated-types.ts

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/destination-actions/src/destinations/snap-audiences/index.ts

Lines changed: 37 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,8 @@
11
import { AudienceDestinationDefinition, defaultValues, IntegrationError } from '@segment/actions-core'
22
import type { Settings, AudienceSettings } from './generated-types'
33
import syncAudience from './syncAudience'
4-
const ACCESS_TOKEN_URL = 'https://accounts.snapchat.com/login/oauth2/access_token'
5-
6-
interface RefreshTokenResponse {
7-
access_token: string
8-
}
9-
interface SnapAudienceResponse {
10-
segments: {
11-
segment: {
12-
id: string
13-
}
14-
}[]
15-
}
16-
interface CreateAudienceReq {
17-
segments: {
18-
name: string
19-
source_type: string
20-
ad_account_id: string
21-
description: string
22-
retention_in_days: number
23-
}[]
24-
}
4+
import { CreateAudienceReq, RefreshTokenResponse, SnapAudienceResponse } from './types'
5+
import { ACCESS_TOKEN_URL, DEFAULT_RETENTION_DAYS } from './constants'
256

267
const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
278
name: 'Snap Audiences (Actions)',
@@ -93,33 +74,18 @@ const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
9374
eventSlug: 'journeys_step_entered_track'
9475
},
9576
{
96-
name: 'Sync Audience with Email',
97-
subscribe: 'type = "track" and context.traits.email exists',
77+
name: 'Sync Engage Audience',
78+
subscribe: 'type = "track" or type = "identify"',
9879
partnerAction: 'syncAudience',
99-
mapping: { ...defaultValues(syncAudience.fields), schema_type: 'EMAIL_SHA256' },
100-
type: 'automatic'
101-
},
102-
{
103-
name: 'Sync Audience with Phone',
104-
subscribe: 'type = "track" and properties.phone exists',
105-
partnerAction: 'syncAudience',
106-
mapping: { ...defaultValues(syncAudience.fields), schema_type: 'PHONE_SHA256' },
107-
type: 'automatic'
108-
},
109-
{
110-
name: 'Sync Audience with Mobile AD ID',
111-
subscribe: 'type = "track" and context.device.advertisingId exists',
112-
partnerAction: 'syncAudience',
113-
mapping: { ...defaultValues(syncAudience.fields), schema_type: 'MOBILE_AD_ID_SHA256' },
80+
mapping: { ...defaultValues(syncAudience.fields)},
11481
type: 'automatic'
11582
}
11683
],
11784
audienceFields: {
11885
customAudienceName: {
11986
type: 'string',
12087
label: 'Audience Name',
121-
description:
122-
'Name for the audience that will be created in Snap. Defaults to the snake_cased Segment audience name if left blank.',
88+
description: 'Name for the audience that will be created in Snap. Defaults to the snake_cased Segment audience name if left blank.',
12389
default: '',
12490
required: false
12591
},
@@ -133,7 +99,7 @@ const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
13399
retention_in_days: {
134100
type: 'number',
135101
label: 'Retention in days',
136-
description: '# of days to retain audience members. (Default retention is lifetime represented as 9999)',
102+
description: 'Number of days to retain audience members. (Default retention is lifetime represented as 9999)',
137103
default: 9999,
138104
required: false
139105
}
@@ -144,44 +110,50 @@ const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
144110
full_audience_sync: false
145111
},
146112
async createAudience(request, createAudienceInput) {
147-
const audienceName = createAudienceInput.audienceName
148-
const ad_account_id = createAudienceInput.settings.ad_account_id
149-
const { customAudienceName, description, retention_in_days } = createAudienceInput.audienceSettings || {}
113+
const {
114+
audienceName,
115+
settings: { ad_account_id } = {},
116+
audienceSettings: {
117+
customAudienceName,
118+
description,
119+
retention_in_days
120+
} = {}
121+
} = createAudienceInput
150122

151123
if (!audienceName) {
152124
throw new IntegrationError('Missing audience name value', 'MISSING_REQUIRED_FIELD', 400)
153125
}
154126

155-
const response = await request(`https://adsapi.snapchat.com/v1/adaccounts/${ad_account_id}/segments`, {
127+
if(!ad_account_id){
128+
throw new IntegrationError('Missing Ad Account ID. Please configure the Ad Account ID in the destination settings.', 'MISSING_REQUIRED_FIELD', 400)
129+
}
130+
131+
const json: CreateAudienceReq = {
132+
segments: [
133+
{
134+
name: customAudienceName || audienceName,
135+
source_type: 'FIRST_PARTY',
136+
ad_account_id,
137+
description: description || `Audience ${audienceName} created by Segment`,
138+
retention_in_days: retention_in_days || DEFAULT_RETENTION_DAYS
139+
}
140+
]
141+
}
142+
143+
const response = await request<SnapAudienceResponse>(`https://adsapi.snapchat.com/v1/adaccounts/${ad_account_id}/segments`, {
156144
method: 'POST',
157-
json: {
158-
segments: [
159-
{
160-
name: customAudienceName !== '' ? customAudienceName : audienceName,
161-
source_type: 'FIRST_PARTY',
162-
ad_account_id,
163-
description,
164-
retention_in_days
165-
}
166-
]
167-
} as CreateAudienceReq
145+
json
168146
})
169147

170-
const data: SnapAudienceResponse = await response.json()
171-
const snapAudienceId = data.segments[0].segment.id
172-
173-
return { externalId: snapAudienceId }
148+
return { externalId: response.data.segments[0].segment.id }
174149
},
175150

176151
getAudience: async (request, { externalId }) => {
177-
const response = await request(`https://adsapi.snapchat.com/v1/segments/${externalId}`, {
152+
const response = await request<SnapAudienceResponse>(`https://adsapi.snapchat.com/v1/segments/${externalId}`, {
178153
method: 'GET'
179154
})
180155

181-
const data: SnapAudienceResponse = await response.json()
182-
const snapAudienceId = data.segments[0].segment.id
183-
184-
return { externalId: snapAudienceId }
156+
return { externalId: response.data.segments[0].segment.id }
185157
}
186158
}
187159
}

0 commit comments

Comments
 (0)