Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 12d62f7
Author: Harsh Joshi <[email protected]>
Date:   Wed Dec 6 10:29:30 2023 +0530

    cleanup

commit 3b8b9ed
Author: Harsh Joshi <[email protected]>
Date:   Mon Dec 4 10:36:54 2023 +0530

    Code changes and unit tests

commit 2edb75e
Merge: 8e9e776 ad48899
Author: Harsh Joshi <[email protected]>
Date:   Wed Nov 29 18:01:45 2023 +0530

    Merge branch 'STRATCONN-3399' into klaviyo-add-to-profile-batch

commit 8e9e776
Author: Elena <[email protected]>
Date:   Wed Nov 29 04:02:37 2023 -0800

    Yahoo audiences 5 (#1742)

    * new audience settings, logging

    * mapping change, device type

commit 7b0fe44
Author: Ankit Gupta <[email protected]>
Date:   Wed Nov 29 17:25:49 2023 +0530

    [STRATCONN] Klaviyo AddToProfileList and RemoveFromProfileList actions with engage setup (#1723)

    * AddToProfileList and RemoveFromProfileList action added

    * added new flow of addProfileToList and RemoveProfileFromList actions in klaviyo

    * completed audience setup for klaviyo

    * updated api key field for klaviyo

    * change in remove from list api test cases

    * full audience sync turned off for audience klaviyo

    * changing default path of external_id

    * Removed debug codes

    * code refactored

    * change in addProfile and removeProfile in klaviyo

    * Resolved build error

    * Resolved build error

    * Added buildHeaders function

    * Seperated addProfile and RemoveProfile Functions

    * Added audience desctiption

    * Change error handling of createProfile function

    * Change error handling of createProfile function

    * Modified in addProfileToList Test case

commit 6db1308
Author: Marín Alcaraz <[email protected]>
Date:   Wed Nov 29 03:54:19 2023 -0800

    Add updateHandler to Actions DV360 (#1726)

    * Add updateHandler to Actions DV360

    * Fix tests

    * update yarn.lock

commit ac78bc7
Author: alfrimpong <[email protected]>
Date:   Wed Nov 29 05:50:15 2023 -0600

    Inc-7055 long term fix: add external ids to message tags (#1744)

    * feat: add external id type & value to message tags

    * feat: add test to enforce passthrough

commit 31e207c
Author: alfrimpong <[email protected]>
Date:   Wed Nov 29 05:44:38 2023 -0600

    Channels-973: parse text field of action buttons (#1738)

    * feat: parse merge tags in action button text

    * chore: added unit test

commit 593b024
Author: Sayan Das <[email protected]>
Date:   Wed Nov 29 17:14:02 2023 +0530

    LR: Fix CSV generator to account for all rows (#1735)

    * Fixed CSV generator to account for all rows

    * Updated CSV processor, tests and snapshots

commit ce3c082
Author: maryamsharif <[email protected]>
Date:   Wed Nov 29 03:43:21 2023 -0800

    [STRATCONN-3376] Add phone number to TikTok Audiences (#1730)

    * Add phone number

    * Fix unit tests

    * Hide enable batching field + adjust names

commit 6fc66be
Author: Chris Brown <[email protected]>
Date:   Wed Nov 29 06:42:32 2023 -0500

    rename full_name to display_name to fix API changes (#1743)

    * rename full_name to display_name to fix API changes

    * Update full_name to display_name in tests

commit 10cc239
Author: Joe Ayoub <[email protected]>
Date:   Wed Nov 29 12:42:06 2023 +0100

    adding default paths for click id and cookie (#1729)

commit 5d80f5e
Author: zhadier39 <[email protected]>
Date:   Wed Nov 29 16:41:16 2023 +0500

    [Hyperengage] Resolved issue with Timezone Offset and Added Missing user_id field in group call (#1733)

    * Add unit and integration tests

    * Updated field descriptions for group, identify and track

    * Updated common fields

    * Fix identify function error

    * Added authentication endpoint

    * Revise tests to enable auth

    * Update default paths for groupId.

    * Implement recommended changes from PR #1621

    * Add url field

    * Resolve pathing issues and add tests/checks for first and last name fields

    * Resolve test issues, payload validation error, and correct context default

    * Fix no user_id field in group call and timezone offset bug

    * Add tests for new functionality

    * Delete packages/destination-actions/src/destinations/liveramp-audiences/audienceEnteredSFTP.types.ts

    Remove auto generated types file on liveramp platform

    * Fix ts error with timeZoneName

    ---------

    Co-authored-by: saadhypng <[email protected]>
    Co-authored-by: Saad Ali <[email protected]>

commit ad48899
Author: Harsh Joshi <[email protected]>
Date:   Wed Nov 29 15:54:05 2023 +0530

    Update error handling

commit e9f2370
Author: Harsh Joshi <[email protected]>
Date:   Fri Nov 24 11:42:37 2023 +0530

    Add enable batching

commit a75cedd
Author: Harsh Joshi <[email protected]>
Date:   Fri Nov 24 11:06:45 2023 +0530

    Add performBatch in upsert profile
  • Loading branch information
harsh-joshi99 committed Dec 6, 2023
1 parent 0a9260e commit 975661d
Show file tree
Hide file tree
Showing 18 changed files with 290 additions and 69 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
Expand Up @@ -4,24 +4,17 @@ import type { Settings, AudienceSettings } from '../generated-types'
import type { Payload } from './generated-types'
import { handleUpdate } from '../shared'

import {
enable_batching,
external_audience_id,
google_gid,
mobile_advertising_id,
partner_provided_id
} from '../properties'
import { enable_batching, external_audience_id, google_gid, mobile_advertising_id, anonymous_id } from '../properties'

const action: ActionDefinition<Settings, Payload, AudienceSettings> = {
title: 'Add to Audience',
description: 'Add a user to a Display & Video 360 audience.',
defaultSubscription: 'event = "Audience Entered"',
fields: {
enable_batching: { ...enable_batching },
external_audience_id: { ...external_audience_id },
anonymous_id: { ...anonymous_id },
mobile_advertising_id: { ...mobile_advertising_id },
google_gid: { ...google_gid },
partner_provided_id: { ...partner_provided_id }
google_gid: { ...google_gid }
},
perform: async (request, { payload, statsContext }) => {
statsContext?.statsClient?.incr('addToAudience', 1, statsContext?.tags)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ErrorCodes, IntegrationError, InvalidAuthenticationError } from '@segment/actions-core'
import { ErrorCodes, IntegrationError } from '@segment/actions-core'
import { InvalidAuthenticationError } from '@segment/actions-core/*'

import { GoogleAPIError } from './types'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ const destination: AudienceDestinationDefinition<Settings, AudienceSettings> = {
description: 'The type of the advertiser account you have linked to this Display & Video 360 destination.',
required: true,
choices: [
{ label: 'Advertiser', value: 'DISPLAY_VIDEO_ADVERTISER' },
{ label: 'Partner', value: 'DISPLAY_VIDEO_PARTNER' },
{ label: 'Publisher', value: 'GOOGLE_AD_MANAGER' }
{ label: 'DISPLAY_VIDEO_ADVERTISER', value: 'DISPLAY_VIDEO_ADVERTISER' },
{ label: 'DISPLAY_VIDEO_PARTNER', value: 'DISPLAY_VIDEO_PARTNER' },
{ label: 'DFP_BY_GOOGLE or GOOGLE_AD_MANAGER', value: 'GOOGLE_AD_MANAGER' }
]
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
import { InputField } from '@segment/actions-core/destination-kit/types'

export const mobile_advertising_id: InputField = {
label: 'Mobile Advertising ID',
description: 'Mobile Advertising ID. This could be a GAID, or IDFA. Remove if not needed.',
export const anonymous_id: InputField = {
label: 'Anonymous ID',
description: 'Anonymous ID',
type: 'string',
required: false,
default: {
'@path': '$.context.device.advertisingId'
}
'@path': '$.anonymousId'
},
readOnly: true
}

export const google_gid: InputField = {
label: 'Google GID',
description: 'Google GID. Remove if not needed.',
export const mobile_advertising_id: InputField = {
label: 'Mobile Advertising ID',
description: 'Mobile Advertising ID',
type: 'string',
required: false,
default: {
'@path': '$.context.traits.google_gid'
}
'@path': '$.context.device.advertisingId'
},
readOnly: true
}

export const partner_provided_id: InputField = {
label: 'Partner Provided ID',
description: 'Partner Provided ID. Remove if not needed.',
export const google_gid: InputField = {
label: 'Google GID',
description: 'Google GID',
type: 'string',
required: false,
default: {
'@path': '$.anonymousId'
}
'@path': '$.context.traits.google_gid' // TODO: Double check on this one because it might need to be explicitly set.
},
readOnly: true
}

export const enable_batching: InputField = {
Expand Down

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
Expand Up @@ -4,24 +4,17 @@ import type { Settings, AudienceSettings } from '../generated-types'
import type { Payload } from './generated-types'
import { handleUpdate } from '../shared'

import {
enable_batching,
external_audience_id,
mobile_advertising_id,
google_gid,
partner_provided_id
} from '../properties'
import { enable_batching, external_audience_id, anonymous_id, mobile_advertising_id, google_gid } from '../properties'

const action: ActionDefinition<Settings, Payload, AudienceSettings> = {
title: 'Remove from Audience',
description: 'Remove users from an audience',
defaultSubscription: 'event = "Audience Exited"',
fields: {
enable_batching: { ...enable_batching },
external_audience_id: { ...external_audience_id },
anonymous_id: { ...anonymous_id },
mobile_advertising_id: { ...mobile_advertising_id },
google_gid: { ...google_gid },
partner_provided_id: { ...partner_provided_id }
google_gid: { ...google_gid }
},
perform: async (request, { payload, statsContext }) => {
statsContext?.statsClient?.incr('removeFromAudience', 1, statsContext?.tags)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const buildHeaders = (audienceSettings: AudienceSettings | undefined, set

return {
// @ts-ignore - TS doesn't know about the oauth property
Authorization: `Bearer ${settings?.oauth?.access_token}`,
Authorization: `Bearer ${settings?.oauth?.accessToken}`,
'Content-Type': 'application/json',
'Login-Customer-Id': `products/${audienceSettings.accountType}/customers/${audienceSettings?.advertiserId}`
}
Expand Down Expand Up @@ -50,9 +50,9 @@ export const assembleRawOps = (payload: UpdateHandlerPayload, operation: ListOpe
})
}

if (payload.partner_provided_id) {
if (payload.anonymous_id) {
rawOperations.push({
UserId: payload.partner_provided_id,
UserId: payload.anonymous_id,
UserIdType: UserIdType.PARTNER_PROVIDED_ID,
UserListId: audienceId,
Delete: isDelete
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import { createTestEvent, createTestIntegration } from '@segment/actions-core'
import Definition from '../../index'
import { API_URL } from '../../config'
import { AggregateAjvError } from '@segment/ajv-human-errors'
import { Mock } from 'jest-mock'

import * as Functions from '../../functions'

jest.mock('../../functions', () => ({
...jest.requireActual('../../functions'),
createImportJobPayload: jest.fn(),
sendImportJobRequest: jest.fn(() => Promise.resolve())
}))

const testDestination = createTestIntegration(Definition)

Expand Down Expand Up @@ -31,6 +40,30 @@ const profileData = {
}
}

const importJobPayload = {
data: {
type: 'profile-bulk-import-job',
attributes: {
profiles: {
data: [
{
type: 'profile',
attributes: {
email: '[email protected]',
external_id: 'fake-external-id'
}
}
]
}
},
relationships: {
lists: {
data: [{ type: 'list', id: listId }]
}
}
}
}

describe('Add List To Profile', () => {
it('should throw error if no list_id/email is provided', async () => {
const event = createTestEvent({
Expand Down Expand Up @@ -70,6 +103,7 @@ describe('Add List To Profile', () => {
})
const mapping = {
external_id: listId,
list_id: listId,
email: {
'@path': '$.traits.email'
}
Expand Down Expand Up @@ -110,6 +144,7 @@ describe('Add List To Profile', () => {
})
const mapping = {
external_id: listId,
list_id: listId,
email: {
'@path': '$.traits.email'
}
Expand All @@ -119,3 +154,113 @@ describe('Add List To Profile', () => {
).resolves.not.toThrowError()
})
})

describe('Add Profile To List Batch', () => {
beforeEach(() => {
nock.cleanAll()
jest.resetAllMocks()
})
afterEach(() => {
jest.resetAllMocks()
})

it('should filter out profiles without email or external_id', async () => {
const events = [
createTestEvent({
context: { personas: { list_id: '123' }, traits: { email: '[email protected]' } }
}),
createTestEvent({
context: { personas: {}, traits: {} }
})
]

const mapping = {
list_id: listId,
email: {
'@path': '$.context.traits.email'
}
}

nock(API_URL).post('/profile-bulk-import-jobs/').reply(200, { success: true })

await testDestination.testBatchAction('addProfileToList', {
settings,
events,
mapping,
useDefaultMappings: true
})

// Check if createImportJobPayload was called with only the valid profile
expect(Functions.createImportJobPayload).toHaveBeenCalledWith(
[
{
list_id: listId,
email: '[email protected]'
}
],
listId
)
})

it('should create an import job payload with the correct listId', async () => {
const events = [
createTestEvent({
context: { personas: { list_id: listId }, traits: { email: '[email protected]' } }
})
]
const mapping = {
list_id: listId,
external_id: 'fake-external-id',
email: {
'@path': '$.context.traits.email'
}
}

nock(API_URL).post('/profile-bulk-import-jobs/').reply(200, { success: true })

await testDestination.testBatchAction('addProfileToList', {
settings,
events,
mapping,
useDefaultMappings: true
})

expect(Functions.createImportJobPayload).toHaveBeenCalledWith(
expect.arrayContaining([
expect.objectContaining({
email: '[email protected]',
external_id: 'fake-external-id',
list_id: listId
})
]),
listId
)
})

it('should send an import job request with the generated payload', async () => {
const events = [
createTestEvent({
context: { personas: { list_id: listId }, traits: { email: '[email protected]' } }
})
]
const mapping = {
list_id: listId,
external_id: 'fake-external-id',
email: {
'@path': '$.context.traits.email'
}
}

;(Functions.createImportJobPayload as Mock).mockImplementation(() => importJobPayload)
nock(API_URL).post('/profile-bulk-import-jobs/', importJobPayload).reply(200, { success: true })

await testDestination.testBatchAction('addProfileToList', {
events,
settings,
mapping,
useDefaultMappings: true
})

expect(Functions.sendImportJobRequest).toHaveBeenCalledWith(expect.anything(), importJobPayload)
})
})

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

Loading

0 comments on commit 975661d

Please sign in to comment.