[Wingify] - new cloud more Destination#3839
Conversation
| } | ||
| }, | ||
| testAuthentication: (_request, { settings }) => { | ||
| if (settings.wingifyAccountId < 1 || settings.wingifyAccountId.toString().length > 7) { |
There was a problem hiding this comment.
The intent for testAuthentication is that you actually check that the credentials passed by the cusomer are valid. If that's what's happening here it's OK. But usually you'd use the request object to make an API request to verify this.
Please confirm.
Also, please throw an InvalidAuthenticationError instead or a regular Error.
There was a problem hiding this comment.
Pull request overview
This PR adds a new cloud-mode destination under packages/destination-actions/src/destinations/wingify (“Wingify Cloud Mode (Actions)”, slug actions-wingify-cloud) with actions for Track, Identify, Page, and Audience sync, plus supporting utilities/types and unit tests.
Changes:
- Introduces the Wingify destination definition (auth + presets + actions).
- Implements four Wingify actions (
trackEvent,identifyUser,pageVisit,syncAudience) plus shared payload utilities/types. - Adds unit tests for the destination and each action.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 23 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/destination-actions/src/destinations/wingify/index.ts | New destination definition (presets, auth, action wiring). |
| packages/destination-actions/src/destinations/wingify/generated-types.ts | Generated Settings type for Wingify destination. |
| packages/destination-actions/src/destinations/wingify/utility.ts | Shared host map, payload formatting, and UUID generation helpers. |
| packages/destination-actions/src/destinations/wingify/types.ts | Shared payload type definitions. |
| packages/destination-actions/src/destinations/wingify/trackEvent/index.ts | Track action implementation posting Wingify event payloads. |
| packages/destination-actions/src/destinations/wingify/trackEvent/generated-types.ts | Generated payload types for Track action. |
| packages/destination-actions/src/destinations/wingify/trackEvent/tests/index.test.ts | Unit tests for Track action behavior/request shape. |
| packages/destination-actions/src/destinations/wingify/identifyUser/index.ts | Identify action implementation mapping traits to Wingify visitor attributes. |
| packages/destination-actions/src/destinations/wingify/identifyUser/generated-types.ts | Generated payload types for Identify action. |
| packages/destination-actions/src/destinations/wingify/identifyUser/tests/index.test.ts | Unit tests for Identify action behavior/request shape. |
| packages/destination-actions/src/destinations/wingify/pageVisit/index.ts | Page action implementation posting page visit payloads. |
| packages/destination-actions/src/destinations/wingify/pageVisit/generated-types.ts | Generated payload types for Page action. |
| packages/destination-actions/src/destinations/wingify/pageVisit/tests/index.test.ts | Unit tests for Page action behavior/request shape. |
| packages/destination-actions/src/destinations/wingify/syncAudience/index.ts | Audience sync action implementation posting audience enter/exit payloads. |
| packages/destination-actions/src/destinations/wingify/syncAudience/generated-types.ts | Generated payload types for Audience sync action. |
| packages/destination-actions/src/destinations/wingify/syncAudience/tests/index.test.ts | Unit tests for Audience sync action behavior/request shape. |
| packages/destination-actions/src/destinations/wingify/tests/index.test.ts | Tests for auth validation and UUID generator. |
| authentication: { | ||
| scheme: 'custom', | ||
| fields: { | ||
| vwoAccountId: { |
|
|
||
| const destination: DestinationDefinition<Settings> = { | ||
| name: 'Wingify Cloud Mode (Actions)', | ||
| slug: 'actions-wingify-cloud', |
|
|
||
| const testDestination = createTestIntegration(Destination) | ||
|
|
||
| const BASE_ENDPOINT = 'https://dev.visualwebsiteoptimizer.com' |
| properties: { | ||
| wingifyUuid: wingifyUuid | ||
| } |
|
|
||
| const testDestination = createTestIntegration(Destination) | ||
|
|
||
| const BASE_ENDPOINT = 'https://dev.visualwebsiteoptimizer.com' |
| const event = createTestEvent({ | ||
| event: 'testEvent', | ||
| properties: { | ||
| wingifyUuid: wingifyUuid, |
| it('should send Page Visit event to Wingify', async () => { | ||
| const event = createTestEvent({ | ||
| properties: { | ||
| wingifyUuid: wingifyUuid |
| it('should send Page Visit event to Wingify', async () => { | ||
| const event = createTestEvent({ | ||
| properties: { | ||
| wingifyUuid: wingifyUuid |
| it('should send Page Visit event to Wingify', async () => { | ||
| const event = createTestEvent({ | ||
| properties: { | ||
| wingifyUuid: wingifyUuid |
| export function formatAttributes(attributes: { [k: string]: unknown } | undefined) { | ||
| const formattedAttributes: { [k: string]: unknown } = {} | ||
| for (const key in attributes) { | ||
| formattedAttributes[`segment.${key}`] = attributes[key] | ||
| } | ||
| return formattedAttributes | ||
| } |
| required: false, | ||
| type: 'string', | ||
| default: { | ||
| '@path': '$.context.ip' |
There was a problem hiding this comment.
Just a heads up here. If a customer sends a payload from a mobile or web device (using Segment mobile or web libraries), then the IP address will be useful.
However if the customer sends data using one of Segment's server side libraries, the IP address will become the IP address of Segment's server. This is probably not very useful to you. So be careful with assigning a default like this to a server side integration.
There was a problem hiding this comment.
You might want to change this in the other actions too.
| const action: ActionDefinition<Settings, Payload> = { | ||
| title: 'Sync Audience', | ||
| description: 'Syncs Segment audiences to Wingify', | ||
| defaultSubscription: 'event = "Audience Entered" or event = "Audience Exited"', |
There was a problem hiding this comment.
Customers can change audience event names, so we should not rely on "Audience Entered" or "Audience Exited". I suggest changing this to type = identify or type = track.
Then see below for how to get the action value.
| } | ||
| } | ||
| }, | ||
| perform: (request, { settings, payload }) => { |
There was a problem hiding this comment.
| perform: (request, { settings, payload }) => { | |
| perform: async (request, { settings, payload, audienceMembership }) => { |
| } else if (payload.name == 'Audience Exited') { | ||
| action = 'audience_exited' | ||
| } | ||
| const wingifyPayload = { |
There was a problem hiding this comment.
| const wingifyPayload = { | |
| action = audienceMembership ? 'audience_entered' : 'audience_exited' |
| default: { | ||
| '@path': '$.properties.audience_key' | ||
| } |
There was a problem hiding this comment.
| default: { | |
| '@path': '$.properties.audience_key' | |
| } | |
| default: { | |
| '@if': { | |
| exists: { '@path': '$.context.personas.computation_key' }, | |
| then: { '@path': '$.context.personas.computation_key' }, | |
| else: { '@path': '$.properties.audience_key' } | |
| } | |
| } |
|
Hi @atharvnagar-git I reviewed the PR and left some comments for you to address. Nothing major, but a bunch of important things. |
Adds a new Wingify Cloud Mode (Actions) cloud destination (actions-wingify-cloud) to support Wingify’s updated event ingestion infrastructure. The existing VWO destination is left unchanged so current integrations keep working.Adds a new Wingify Cloud Mode (Actions) cloud destination (actions-wingify-cloud) to support Wingify’s updated event ingestion infrastructure. The existing VWO destination is left unchanged so current integrations keep working.
Testing
Include any additional information about the testing you have completed to
ensure your changes behave as expected. For a speedy review, please check
any of the tasks you completed below during your testing.
Security Review
Please ensure sensitive data is properly protected in your integration.
type: 'password'New Destination Checklist
verioning-info.tsfile. example