Skip to content

Commit fb323ce

Browse files
committed
Squashed commit of the following:
commit 9e7fdba Author: Ankit Gupta <ankit.gupta@segment.com> Date: Tue Feb 10 13:18:00 2026 +0530 Remove debug console.log statement Removed console.log(request) from performHook that was left in during development. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> commit 25a1f91 Author: Ankit Gupta <ankit.gupta@segment.com> Date: Tue Feb 10 13:14:56 2026 +0530 Handled required field
1 parent 6366770 commit fb323ce

File tree

4 files changed

+151
-4
lines changed

4 files changed

+151
-4
lines changed

packages/destination-actions/src/destinations/linkedin-conversions/api/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,9 @@ export class LinkedInConversions {
463463
userIds,
464464
userInfo: payload.userInfo,
465465
// only 1 externalId value allowed currently in the externalIds array by LinkedIn currently Oct 2025
466-
...(Array.isArray(payload?.externalIds) && payload.externalIds.length > 0 ? { externalIds: [payload.externalIds[0]] } : {})
466+
...(Array.isArray(payload?.externalIds) && payload.externalIds.length > 0
467+
? { externalIds: [payload.externalIds[0]] }
468+
: {})
467469
}
468470
}
469471
})
@@ -493,7 +495,9 @@ export class LinkedInConversions {
493495
userIds,
494496
userInfo: payload.userInfo,
495497
// only 1 externalId value allowed currently in the externalIds array by LinkedIn currently Oct 2025
496-
...(Array.isArray(payload?.externalIds) && payload.externalIds.length > 0 ? { externalIds: [payload.externalIds[0]] } : {})
498+
...(Array.isArray(payload?.externalIds) && payload.externalIds.length > 0
499+
? { externalIds: [payload.externalIds[0]] }
500+
: {})
497501
}
498502
}
499503
})

packages/destination-actions/src/destinations/linkedin-conversions/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export const DEPENDS_ON_CONVERSION_RULE_ID: DependsOnConditions = {
6363
conditions: [
6464
{
6565
fieldKey: 'conversionRuleId',
66-
operator: 'is_not',
66+
operator: 'is',
6767
value: undefined
6868
}
6969
]

packages/destination-actions/src/destinations/linkedin-conversions/streamConversion/__tests__/index.test.ts

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,3 +764,142 @@ describe('LinkedinConversions.timestamp', () => {
764764
).resolves.not.toThrowError()
765765
})
766766
})
767+
768+
describe('LinkedinConversions.onMappingSave - Conversion Rule Creation', () => {
769+
it('should successfully create a new conversion rule with all required fields', async () => {
770+
const mockConversionRuleResponse = {
771+
id: '123456',
772+
name: 'Test Conversion Rule',
773+
type: 'PURCHASE',
774+
attributionType: 'LAST_TOUCH_BY_CAMPAIGN',
775+
postClickAttributionWindowSize: 30,
776+
viewThroughAttributionWindowSize: 7
777+
}
778+
779+
nock(`${BASE_URL}/conversions`)
780+
.post('', {
781+
name: 'Test Conversion Rule',
782+
account: 'urn:li:sponsoredAccount:12345',
783+
conversionMethod: 'CONVERSIONS_API',
784+
postClickAttributionWindowSize: 30,
785+
viewThroughAttributionWindowSize: 7,
786+
attributionType: 'LAST_TOUCH_BY_CAMPAIGN',
787+
type: 'PURCHASE'
788+
})
789+
.reply(201, mockConversionRuleResponse)
790+
791+
nock(`${BASE_URL}/conversionEvents`).post(/.*/).reply(201)
792+
793+
// Test that action can use the created conversion rule
794+
await expect(
795+
testDestination.testAction('streamConversion', {
796+
event,
797+
settings,
798+
mapping: {
799+
email: { '@path': '$.context.traits.email' },
800+
conversionHappenedAt: {
801+
'@path': '$.timestamp'
802+
},
803+
onMappingSave: {
804+
inputs: {},
805+
outputs: {
806+
id: '123456',
807+
name: 'Test Conversion Rule',
808+
conversionType: 'PURCHASE',
809+
attribution_type: 'LAST_TOUCH_BY_CAMPAIGN',
810+
post_click_attribution_window_size: 30,
811+
view_through_attribution_window_size: 7
812+
}
813+
},
814+
enable_batching: true,
815+
batch_size: 5000
816+
}
817+
})
818+
).resolves.not.toThrowError()
819+
})
820+
821+
it('should successfully use an existing conversion rule when conversionRuleId is provided', async () => {
822+
nock(`${BASE_URL}/conversionEvents`).post(/.*/).reply(201)
823+
824+
await expect(
825+
testDestination.testAction('streamConversion', {
826+
event,
827+
settings,
828+
mapping: {
829+
email: { '@path': '$.context.traits.email' },
830+
conversionHappenedAt: {
831+
'@path': '$.timestamp'
832+
},
833+
onMappingSave: {
834+
inputs: {},
835+
outputs: {
836+
id: 'existing123',
837+
name: 'Existing Conversion Rule',
838+
conversionType: 'LEAD',
839+
attribution_type: 'LAST_TOUCH_BY_CONVERSION',
840+
post_click_attribution_window_size: 7,
841+
view_through_attribution_window_size: 1
842+
}
843+
},
844+
enable_batching: true,
845+
batch_size: 5000
846+
}
847+
})
848+
).resolves.not.toThrowError()
849+
})
850+
851+
it('should verify conversion rule creation API request format', async () => {
852+
const mockConversionRuleResponse = {
853+
id: '789456',
854+
name: 'Default Windows Rule',
855+
type: 'SIGN_UP',
856+
attributionType: 'LAST_TOUCH_BY_CAMPAIGN',
857+
postClickAttributionWindowSize: 30,
858+
viewThroughAttributionWindowSize: 7
859+
}
860+
861+
const creationRequest = nock(`${BASE_URL}/conversions`)
862+
.post('', {
863+
name: 'Default Windows Rule',
864+
account: 'urn:li:sponsoredAccount:12345',
865+
conversionMethod: 'CONVERSIONS_API',
866+
postClickAttributionWindowSize: 30,
867+
viewThroughAttributionWindowSize: 7,
868+
attributionType: 'LAST_TOUCH_BY_CAMPAIGN',
869+
type: 'SIGN_UP'
870+
})
871+
.reply(201, mockConversionRuleResponse)
872+
873+
nock(`${BASE_URL}/conversionEvents`).post(/.*/).reply(201)
874+
875+
await expect(
876+
testDestination.testAction('streamConversion', {
877+
event,
878+
settings,
879+
mapping: {
880+
email: { '@path': '$.context.traits.email' },
881+
conversionHappenedAt: {
882+
'@path': '$.timestamp'
883+
},
884+
onMappingSave: {
885+
inputs: {},
886+
outputs: {
887+
id: '789456',
888+
name: 'Default Windows Rule',
889+
conversionType: 'SIGN_UP',
890+
attribution_type: 'LAST_TOUCH_BY_CAMPAIGN',
891+
post_click_attribution_window_size: 30,
892+
view_through_attribution_window_size: 7
893+
}
894+
},
895+
enable_batching: true,
896+
batch_size: 5000
897+
}
898+
})
899+
).resolves.not.toThrowError()
900+
901+
// Verify the conversion rule creation API was not called in this test
902+
// (since we're providing existing outputs)
903+
expect(creationRequest.isDone()).toBe(false)
904+
})
905+
})

packages/destination-actions/src/destinations/linkedin-conversions/streamConversion/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,22 @@ const action: ActionDefinition<Settings, Payload, undefined, OnMappingSaveInputs
5959
type: 'string',
6060
label: 'Name',
6161
description: 'The name of the conversion rule.',
62+
required: true,
6263
depends_on: DEPENDS_ON_CONVERSION_RULE_ID
6364
},
6465
conversionType: {
6566
type: 'string',
6667
label: 'Conversion Type',
6768
description: 'The type of conversion rule.',
69+
required: true,
6870
choices: CONVERSION_TYPE_OPTIONS,
6971
depends_on: DEPENDS_ON_CONVERSION_RULE_ID
7072
},
7173
attribution_type: {
7274
label: 'Attribution Type',
7375
description: 'The attribution type for the conversion rule.',
7476
type: 'string',
77+
required: true,
7578
choices: [
7679
{ label: 'Each Campaign', value: 'LAST_TOUCH_BY_CAMPAIGN' },
7780
{ label: 'Single Campaign', value: 'LAST_TOUCH_BY_CONVERSION' }
@@ -284,7 +287,8 @@ const action: ActionDefinition<Settings, Payload, undefined, OnMappingSaveInputs
284287
},
285288
externalIds: {
286289
label: 'External ID',
287-
description: "An identifier your organization uses for the user. See [LinkedIn's documentation](https://learn.microsoft.com/en-us/linkedin/marketing/conversions/custom-matching-identifiers?view=li-lms-2025-08) for more details.",
290+
description:
291+
"An identifier your organization uses for the user. See [LinkedIn's documentation](https://learn.microsoft.com/en-us/linkedin/marketing/conversions/custom-matching-identifiers?view=li-lms-2025-08) for more details.",
288292
type: 'string',
289293
multiple: true,
290294
required: false

0 commit comments

Comments
 (0)