From dc5d3cf0a625478a98667e2feca40d52e57a6cdb Mon Sep 17 00:00:00 2001 From: GitHub Actions <noreply@github.com> Date: Fri, 25 Oct 2024 10:06:09 +0000 Subject: [PATCH 1/3] chore(release): 1.83.0 --- CHANGELOG.md | 21 +++++++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4d972f67c..bcfd6f2835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,27 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.83.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.82.2...v1.83.0) (2024-10-25) + + +### Features + +* add support for identity stitching for shopify pixel flow ([#3818](https://github.com/rudderlabs/rudder-transformer/issues/3818)) ([3a09181](https://github.com/rudderlabs/rudder-transformer/commit/3a091810bff12ae893c16b514c07d17e6374062a)) +* onboard tune destination ([#3795](https://github.com/rudderlabs/rudder-transformer/issues/3795)) ([741f0c6](https://github.com/rudderlabs/rudder-transformer/commit/741f0c6d6714cf760ce98cc9354b61f7b5ce4684)) +* snowpipe streaming ([#3740](https://github.com/rudderlabs/rudder-transformer/issues/3740)) ([21b1039](https://github.com/rudderlabs/rudder-transformer/commit/21b1039c26067b4896a15adf8b10a044e69cb495)) +* support for multiple zap urls ([#3825](https://github.com/rudderlabs/rudder-transformer/issues/3825)) ([f79dfe7](https://github.com/rudderlabs/rudder-transformer/commit/f79dfe74b447b8ccd80287e143ff771688c510be)) + + +### Bug Fixes + +* add missing field for pinterest_tag single product events ([f781a84](https://github.com/rudderlabs/rudder-transformer/commit/f781a84ade98649d68cebf4da13c2ceff8df2df2)) +* add missing field for pinterest_tag single product events ([#3826](https://github.com/rudderlabs/rudder-transformer/issues/3826)) ([4a63277](https://github.com/rudderlabs/rudder-transformer/commit/4a63277efd0b4357d8321618640d1a0ba2a47d71)) +* heap userId extraction ([#3801](https://github.com/rudderlabs/rudder-transformer/issues/3801)) ([e578413](https://github.com/rudderlabs/rudder-transformer/commit/e57841396ad666d716e195fbd4e9b74a63bf5191)) +* not allowing empty string or null values for mandatory fields in zoho ([#3800](https://github.com/rudderlabs/rudder-transformer/issues/3800)) ([fcd8d99](https://github.com/rudderlabs/rudder-transformer/commit/fcd8d997fe815d61d21ffff235b0799e69b7ded9)) +* populate source destination info env set properly ([#3806](https://github.com/rudderlabs/rudder-transformer/issues/3806)) ([d730daf](https://github.com/rudderlabs/rudder-transformer/commit/d730dafbbd2de30b67c35db8ca05396a98a8d2e0)) +* str replace is not a function error ([#3799](https://github.com/rudderlabs/rudder-transformer/issues/3799)) ([8f18e1a](https://github.com/rudderlabs/rudder-transformer/commit/8f18e1aca70ab68e3f157a4632d63ae7cec0e87b)) +* update order_id in checkout events, messageId in pixel events ([#3794](https://github.com/rudderlabs/rudder-transformer/issues/3794)) ([427be71](https://github.com/rudderlabs/rudder-transformer/commit/427be71a91df8495f81b42d2b58aa490db439b23)) + ### [1.82.2](https://github.com/rudderlabs/rudder-transformer/compare/v1.82.1...v1.82.2) (2024-10-18) diff --git a/package-lock.json b/package-lock.json index 77cc67cc72..ccf7ed2c2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rudder-transformer", - "version": "1.82.2", + "version": "1.83.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rudder-transformer", - "version": "1.82.2", + "version": "1.83.0", "license": "ISC", "dependencies": { "@amplitude/ua-parser-js": "0.7.24", diff --git a/package.json b/package.json index f87249e77c..79571462d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rudder-transformer", - "version": "1.82.2", + "version": "1.83.0", "description": "", "homepage": "https://github.com/rudderlabs/rudder-transformer#readme", "bugs": { From e9c5a755e6ff2d46aafcc3c6117871c42d750ace Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:14:39 +0530 Subject: [PATCH 2/3] chore: allow only mapped in properties, update event name (#3830) * chore: allow only mapped in properties, update event name * chore: remove redundant checks * chore: add jsdoc descriptions * chore: address comments --- src/v1/sources/shopify/config.js | 2 +- src/v1/sources/shopify/pixelUtils.js | 58 +- src/v1/sources/shopify/pixelUtils.test.js | 636 ++++++++++++++++-- .../pixelTestScenarios/CheckoutEventsTests.ts | 29 +- .../pixelTestScenarios/ProductEventsTests.ts | 150 ----- 5 files changed, 631 insertions(+), 244 deletions(-) diff --git a/src/v1/sources/shopify/config.js b/src/v1/sources/shopify/config.js index 57e7e168a1..5d88353d60 100644 --- a/src/v1/sources/shopify/config.js +++ b/src/v1/sources/shopify/config.js @@ -27,7 +27,7 @@ const PIXEL_EVENT_MAPPING = { product_viewed: 'Product Viewed', collection_viewed: 'Collection Viewed', checkout_started: 'Checkout Started', - checkout_completed: 'Checkout Completed', + checkout_completed: 'Order Completed', checkout_address_info_submitted: 'Checkout Address Info Submitted', checkout_contact_info_submitted: 'Checkout Contact Info Submitted', checkout_shipping_info_submitted: 'Checkout Shipping Info Submitted', diff --git a/src/v1/sources/shopify/pixelUtils.js b/src/v1/sources/shopify/pixelUtils.js index 4c39e80549..9abef5c2f8 100644 --- a/src/v1/sources/shopify/pixelUtils.js +++ b/src/v1/sources/shopify/pixelUtils.js @@ -30,10 +30,14 @@ function setNestedValue(object, path, value) { }, object); } -function mapObjectKeys(sourceObject, keyMappings) { - if (!Array.isArray(keyMappings)) { - throw new TypeError('keyMappings should be an array'); - } +/* + * Creates a copy of the source object with the keys mapped to the destination keys + * Keys that are not present in the mapping will be copied as is + * @param {Object} sourceObject + * @param {Array} keyMappings + * @returns {Object} resultObject + */ +function mapContextObjectKeys(sourceObject, keyMappings) { const resultObject = { ...sourceObject }; // eslint-disable-next-line @typescript-eslint/no-shadow @@ -46,10 +50,31 @@ function mapObjectKeys(sourceObject, keyMappings) { }, resultObject); } +/* + * Maps the keys of the source object to the destination object + * Only the keys that are present in the mapping will be copied + * @param {Object} sourceObject + * @param {Array} keyMappings + * @returns {Object} trackProperties + */ +function mapObjectKeys(sourceObject, keyMappings) { + const trackProperties = {}; + + keyMappings.forEach(({ sourceKeys, destKeys }) => { + const value = getNestedValue(sourceObject, sourceKeys); + if (value !== undefined) { + setNestedValue(trackProperties, destKeys, value); + } + }); + + return trackProperties; +} + const createMessage = (eventType, eventName, properties, context) => { const message = new Message(INTEGERATION); message.setEventType(eventType); - message.setEventName(eventName); + if (eventType === EventType.TRACK) message.setEventName(eventName); + else message.name = eventName; message.properties = properties; message.context = context; return message; @@ -57,13 +82,8 @@ const createMessage = (eventType, eventName, properties, context) => { const pageViewedEventBuilder = (inputEvent) => { const { data, context } = inputEvent; - const pageEventContextValues = mapObjectKeys(context, contextualFieldMappingJSON); - const message = new Message(INTEGERATION); - message.name = 'Page View'; - message.setEventType(EventType.PAGE); - message.properties = { ...data }; - message.context = { ...pageEventContextValues }; - return message; + const pageEventContextValues = mapContextObjectKeys(context, contextualFieldMappingJSON); + return createMessage(EventType.PAGE, 'Page View', { ...data }, pageEventContextValues); }; const cartViewedEventBuilder = (inputEvent) => { @@ -83,7 +103,7 @@ const cartViewedEventBuilder = (inputEvent) => { cart_id: inputEvent.data.cart.id, total, }; - const contextualPayload = mapObjectKeys(inputEvent.context, contextualFieldMappingJSON); + const contextualPayload = mapContextObjectKeys(inputEvent.context, contextualFieldMappingJSON); return createMessage(EventType.TRACK, 'Cart Viewed', properties, contextualPayload); }; @@ -102,7 +122,7 @@ const productListViewedEventBuilder = (inputEvent) => { products, }; - const contextualPayload = mapObjectKeys(inputEvent.context, contextualFieldMappingJSON); + const contextualPayload = mapContextObjectKeys(inputEvent.context, contextualFieldMappingJSON); return createMessage(EventType.TRACK, 'Product List Viewed', properties, contextualPayload); }; @@ -110,7 +130,7 @@ const productViewedEventBuilder = (inputEvent) => { const properties = { ...mapObjectKeys(inputEvent.data, productViewedEventMappingJSON), }; - const contextualPayload = mapObjectKeys(inputEvent.context, contextualFieldMappingJSON); + const contextualPayload = mapContextObjectKeys(inputEvent.context, contextualFieldMappingJSON); return createMessage(EventType.TRACK, 'Product Viewed', properties, contextualPayload); }; @@ -118,7 +138,7 @@ const productToCartEventBuilder = (inputEvent) => { const properties = { ...mapObjectKeys(inputEvent.data, productToCartEventMappingJSON), }; - const contextualPayload = mapObjectKeys(inputEvent.context, contextualFieldMappingJSON); + const contextualPayload = mapContextObjectKeys(inputEvent.context, contextualFieldMappingJSON); return createMessage( EventType.TRACK, PIXEL_EVENT_MAPPING[inputEvent.name], @@ -148,7 +168,7 @@ const checkoutEventBuilder = (inputEvent) => { value: inputEvent?.data?.checkout?.totalPrice?.amount, tax: inputEvent?.data?.checkout?.totalTax?.amount, }; - const contextualPayload = mapObjectKeys(inputEvent.context, contextualFieldMappingJSON); + const contextualPayload = mapContextObjectKeys(inputEvent.context, contextualFieldMappingJSON); return createMessage( EventType.TRACK, PIXEL_EVENT_MAPPING[inputEvent.name], @@ -158,7 +178,7 @@ const checkoutEventBuilder = (inputEvent) => { }; const checkoutStepEventBuilder = (inputEvent) => { - const contextualPayload = mapObjectKeys(inputEvent.context, contextualFieldMappingJSON); + const contextualPayload = mapContextObjectKeys(inputEvent.context, contextualFieldMappingJSON); const properties = { ...inputEvent.data.checkout, }; @@ -174,7 +194,7 @@ const searchEventBuilder = (inputEvent) => { const properties = { query: inputEvent.data.searchResult.query, }; - const contextualPayload = mapObjectKeys(inputEvent.context, contextualFieldMappingJSON); + const contextualPayload = mapContextObjectKeys(inputEvent.context, contextualFieldMappingJSON); return createMessage( EventType.TRACK, PIXEL_EVENT_MAPPING[inputEvent.name], diff --git a/src/v1/sources/shopify/pixelUtils.test.js b/src/v1/sources/shopify/pixelUtils.test.js index ed64862228..4bff8eada4 100644 --- a/src/v1/sources/shopify/pixelUtils.test.js +++ b/src/v1/sources/shopify/pixelUtils.test.js @@ -82,21 +82,6 @@ describe('utilV2.js', () => { price: 629.95, quantity: 2, variant: 'The Multi-managed Snowboard', - merchandise: { - id: '41327143157873', - price: { - amount: 629.95, - currencyCode: 'USD', - }, - product: { - title: 'The Multi-managed Snowboard', - }, - title: 'Default Title', - untranslatedTitle: 'Default Title', - }, - cost: { - totalAmount: { amount: 1259.9, currencyCode: 'USD' }, - }, }, ], cart_id: '123', @@ -112,8 +97,27 @@ describe('utilV2.js', () => { data: { collection: { productVariants: [ - { id: 'product123', name: 'Product 123' }, - { id: 'product456', name: 'Product 456' }, + { + price: { + amount: 10, + currencyCode: 'USD', + }, + product: { + title: 'Gift Card', + vendor: 'Snowboard Vendor', + id: '7234590605425', + untranslatedTitle: 'Gift Card', + url: '/products/gift-card', + type: 'giftcard', + }, + id: '41327142895729', + image: { + src: '//store.myshopify.com/cdn/shop/files/gift_card.png?v=1724736596', + }, + sku: '', + title: '$10', + untranslatedTitle: '$10', + }, ], }, }, @@ -127,8 +131,17 @@ describe('utilV2.js', () => { cart_id: 'client123', list_id: 'list123', products: [ - { id: 'product123', name: 'Product 123' }, - { id: 'product456', name: 'Product 456' }, + { + brand: 'Snowboard Vendor', + category: 'giftcard', + image_url: '//store.myshopify.com/cdn/shop/files/gift_card.png?v=1724736596', + name: '$10', + price: 10, + product_id: '7234590605425', + sku: '', + url: '/products/gift-card', + variant: 'Gift Card', + }, ], }); expect(message.context).toEqual({ userAgent: 'Mozilla/5.0' }); @@ -138,12 +151,43 @@ describe('utilV2.js', () => { describe('productViewedEventBuilder', () => { it('should build a product viewed event message', () => { const inputEvent = { - data: { id: 'product123', name: 'Product 123' }, + data: { + productVariant: { + price: { + amount: 749.95, + currencyCode: 'USD', + }, + product: { + title: 'The Collection Snowboard: Liquid', + vendor: 'Hydrogen Vendor', + id: '7234590834801', + untranslatedTitle: 'The Collection Snowboard: Liquid', + url: '/products/the-collection-snowboard-liquid', + type: 'snowboard', + }, + id: '41327143321713', + image: { + src: '//store.myshopify.com/cdn/shop/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6.jpg?v=1724736600', + }, + sku: '', + title: 'Default Title', + untranslatedTitle: 'Default Title', + }, + }, context: { userAgent: 'Mozilla/5.0' }, }; const message = productViewedEventBuilder(inputEvent); expect(message).toBeInstanceOf(Message); - expect(message.properties).toEqual({ id: 'product123', name: 'Product 123' }); + expect(message.properties).toEqual({ + brand: 'Hydrogen Vendor', + category: 'snowboard', + currency: 'USD', + name: 'The Collection Snowboard: Liquid', + price: 749.95, + product_id: '7234590834801', + url: '/products/the-collection-snowboard-liquid', + variant: 'The Collection Snowboard: Liquid', + }); expect(message.context).toEqual({ userAgent: 'Mozilla/5.0' }); }); }); @@ -151,13 +195,56 @@ describe('utilV2.js', () => { describe('productToCartEventBuilder', () => { it('should build a product to cart event message', () => { const inputEvent = { - data: { id: 'product123', name: 'Product 123' }, + data: { + cartLine: { + cost: { + totalAmount: { + amount: 749.95, + currencyCode: 'USD', + }, + }, + merchandise: { + id: '41327143321713', + image: { + src: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6.jpg?v=1724736600', + }, + price: { + amount: 749.95, + currencyCode: 'USD', + }, + product: { + id: '7234590834801', + title: 'The Collection Snowboard: Liquid', + vendor: 'Hydrogen Vendor', + type: 'snowboard', + untranslatedTitle: 'The Collection Snowboard: Liquid', + url: '/products/the-collection-snowboard-liquid?variant=41327143321713', + }, + sku: '', + title: null, + untranslatedTitle: null, + }, + quantity: 1, + }, + }, context: { userAgent: 'Mozilla/5.0' }, name: 'add_to_cart', }; const message = productToCartEventBuilder(inputEvent); expect(message).toBeInstanceOf(Message); - expect(message.properties).toEqual({ id: 'product123', name: 'Product 123' }); + expect(message.properties).toEqual({ + brand: 'Hydrogen Vendor', + category: 'snowboard', + image_url: + 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6.jpg?v=1724736600', + name: null, + price: 749.95, + product_id: '7234590834801', + quantity: 1, + sku: '', + url: '/products/the-collection-snowboard-liquid?variant=41327143321713', + variant: 'The Collection Snowboard: Liquid', + }); expect(message.context).toEqual({ userAgent: 'Mozilla/5.0' }); }); }); @@ -167,20 +254,128 @@ describe('utilV2.js', () => { const inputEvent = { data: { checkout: { + buyerAcceptsEmailMarketing: false, + buyerAcceptsSmsMarketing: false, + attributes: [], + token: '5f7028e0bd5225c17b24bdaa0c09f914', + currencyCode: 'USD', + discountApplications: [], + discountsAmount: { + amount: 0, + currencyCode: 'USD', + }, + email: '', + phone: '', lineItems: [ - { id: 'product123', name: 'Product 123' }, - { id: 'product456', name: 'Product 456' }, + { + discountAllocations: [], + id: '41327143321713', + quantity: 2, + title: 'The Collection Snowboard: Liquid', + variant: { + id: '41327143321713', + image: { + src: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6_64x64.jpg?v=1724736600', + }, + price: { + amount: 749.95, + currencyCode: 'USD', + }, + product: { + id: '7234590834801', + title: 'The Collection Snowboard: Liquid', + vendor: 'Hydrogen Vendor', + type: 'snowboard', + untranslatedTitle: 'The Collection Snowboard: Liquid', + url: '/products/the-collection-snowboard-liquid', + }, + sku: null, + title: null, + untranslatedTitle: null, + }, + finalLinePrice: { + amount: 1499.9, + currencyCode: 'USD', + }, + sellingPlanAllocation: null, + properties: [], + }, + { + discountAllocations: [], + id: '41327143157873', + quantity: 2, + title: 'The Multi-managed Snowboard', + variant: { + id: '41327143157873', + image: { + src: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_9129b69a-0c7b-4f66-b6cf-c4222f18028a_64x64.jpg?v=1724736597', + }, + price: { + amount: 629.95, + currencyCode: 'USD', + }, + product: { + id: '7234590736497', + title: 'The Multi-managed Snowboard', + vendor: 'Multi-managed Vendor', + type: 'snowboard', + untranslatedTitle: 'The Multi-managed Snowboard', + url: '/products/the-multi-managed-snowboard', + }, + sku: 'sku-managed-1', + title: null, + untranslatedTitle: null, + }, + finalLinePrice: { + amount: 1259.9, + currencyCode: 'USD', + }, + sellingPlanAllocation: null, + properties: [], + }, ], + localization: { + country: { + isoCode: 'US', + }, + language: { + isoCode: 'en-US', + }, + market: { + id: 'gid://shopify/Market/23505895537', + handle: 'us', + }, + }, order: { - id: 'order123', + id: null, + customer: { + id: null, + isFirstOrder: null, + }, }, - token: 'checkout123', - totalPrice: { amount: 200 }, - currencyCode: 'USD', - discountsAmount: { amount: 10 }, - shippingLine: { price: { amount: 5 } }, - subtotalPrice: { amount: 185 }, - totalTax: { amount: 15 }, + delivery: { + selectedDeliveryOptions: [], + }, + subtotalPrice: { + amount: 2759.8, + currencyCode: 'USD', + }, + shippingLine: { + price: { + amount: 0, + currencyCode: 'USD', + }, + }, + smsMarketingPhone: null, + totalTax: { + amount: 0, + currencyCode: 'USD', + }, + totalPrice: { + amount: 2759.8, + currencyCode: 'USD', + }, + transactions: [], }, }, id: 'order123', @@ -191,18 +386,42 @@ describe('utilV2.js', () => { expect(message).toBeInstanceOf(Message); expect(message.properties).toEqual({ products: [ - { id: 'product123', name: 'Product 123' }, - { id: 'product456', name: 'Product 456' }, + { + brand: 'Hydrogen Vendor', + category: 'snowboard', + image_url: + 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6_64x64.jpg?v=1724736600', + name: 'The Collection Snowboard: Liquid', + price: 749.95, + product_id: '7234590834801', + quantity: 2, + sku: null, + url: '/products/the-collection-snowboard-liquid', + variant: 'The Collection Snowboard: Liquid', + }, + { + brand: 'Multi-managed Vendor', + category: 'snowboard', + image_url: + 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_9129b69a-0c7b-4f66-b6cf-c4222f18028a_64x64.jpg?v=1724736597', + name: 'The Multi-managed Snowboard', + price: 629.95, + product_id: '7234590736497', + quantity: 2, + sku: 'sku-managed-1', + url: '/products/the-multi-managed-snowboard', + variant: 'The Multi-managed Snowboard', + }, ], - order_id: 'order123', - checkout_id: 'checkout123', - total: 200, + order_id: null, + checkout_id: '5f7028e0bd5225c17b24bdaa0c09f914', + total: 2759.8, currency: 'USD', - discount: 10, - shipping: 5, - revenue: 185, - value: 200, - tax: 15, + discount: 0, + shipping: 0, + revenue: 2759.8, + value: 2759.8, + tax: 0, }); expect(message.context).toEqual({ userAgent: 'Mozilla/5.0' }); }); @@ -213,8 +432,169 @@ describe('utilV2.js', () => { const inputEvent = { data: { checkout: { - step: 1, - action: 'shipping_info_submitted', + buyerAcceptsEmailMarketing: false, + buyerAcceptsSmsMarketing: false, + attributes: [], + billingAddress: { + address1: null, + address2: null, + city: null, + country: 'US', + countryCode: 'US', + firstName: null, + lastName: null, + phone: null, + province: null, + provinceCode: null, + zip: null, + }, + token: '5f7028e0bd5225c17b24bdaa0c09f914', + currencyCode: 'USD', + discountApplications: [], + discountsAmount: { + amount: 0, + currencyCode: 'USD', + }, + email: 'test-user@sampleemail.com', + phone: '', + lineItems: [ + { + discountAllocations: [], + id: '41327143321713', + quantity: 2, + title: 'The Collection Snowboard: Liquid', + variant: { + id: '41327143321713', + image: { + src: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6_64x64.jpg?v=1724736600', + }, + price: { + amount: 749.95, + currencyCode: 'USD', + }, + product: { + id: '7234590834801', + title: 'The Collection Snowboard: Liquid', + vendor: 'Hydrogen Vendor', + type: 'snowboard', + untranslatedTitle: 'The Collection Snowboard: Liquid', + url: '/products/the-collection-snowboard-liquid', + }, + sku: null, + title: null, + untranslatedTitle: null, + }, + finalLinePrice: { + amount: 1499.9, + currencyCode: 'USD', + }, + sellingPlanAllocation: null, + properties: [], + }, + { + discountAllocations: [], + id: '41327143157873', + quantity: 2, + title: 'The Multi-managed Snowboard', + variant: { + id: '41327143157873', + image: { + src: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_9129b69a-0c7b-4f66-b6cf-c4222f18028a_64x64.jpg?v=1724736597', + }, + price: { + amount: 629.95, + currencyCode: 'USD', + }, + product: { + id: '7234590736497', + title: 'The Multi-managed Snowboard', + vendor: 'Multi-managed Vendor', + type: 'snowboard', + untranslatedTitle: 'The Multi-managed Snowboard', + url: '/products/the-multi-managed-snowboard', + }, + sku: 'sku-managed-1', + title: null, + untranslatedTitle: null, + }, + finalLinePrice: { + amount: 1259.9, + currencyCode: 'USD', + }, + sellingPlanAllocation: null, + properties: [], + }, + ], + localization: { + country: { + isoCode: 'US', + }, + language: { + isoCode: 'en-US', + }, + market: { + id: 'gid://shopify/Market/23505895537', + handle: 'us', + }, + }, + order: { + id: null, + customer: { + id: null, + isFirstOrder: null, + }, + }, + delivery: { + selectedDeliveryOptions: [ + { + cost: { + amount: 0, + currencyCode: 'USD', + }, + costAfterDiscounts: { + amount: 0, + currencyCode: 'USD', + }, + description: null, + handle: '5f7028e0bd5225c17b24bdaa0c09f914-8388085074acab7e91de633521be86f0', + title: 'Economy', + type: 'shipping', + }, + ], + }, + shippingAddress: { + address1: 'Queens Center', + address2: null, + city: 'Elmhurst', + country: 'US', + countryCode: 'US', + firstName: 'test', + lastName: 'user', + phone: null, + province: 'NY', + provinceCode: 'NY', + zip: '11373', + }, + subtotalPrice: { + amount: 2759.8, + currencyCode: 'USD', + }, + shippingLine: { + price: { + amount: 0, + currencyCode: 'USD', + }, + }, + smsMarketingPhone: null, + totalTax: { + amount: 0, + currencyCode: 'USD', + }, + totalPrice: { + amount: 2759.8, + currencyCode: 'USD', + }, + transactions: [], }, }, context: { userAgent: 'Mozilla/5.0' }, @@ -222,7 +602,171 @@ describe('utilV2.js', () => { }; const message = checkoutStepEventBuilder(inputEvent); expect(message).toBeInstanceOf(Message); - expect(message.properties).toEqual({ step: 1, action: 'shipping_info_submitted' }); + expect(message.properties).toEqual({ + attributes: [], + billingAddress: { + address1: null, + address2: null, + city: null, + country: 'US', + countryCode: 'US', + firstName: null, + lastName: null, + phone: null, + province: null, + provinceCode: null, + zip: null, + }, + buyerAcceptsEmailMarketing: false, + buyerAcceptsSmsMarketing: false, + currencyCode: 'USD', + delivery: { + selectedDeliveryOptions: [ + { + cost: { + amount: 0, + currencyCode: 'USD', + }, + costAfterDiscounts: { + amount: 0, + currencyCode: 'USD', + }, + description: null, + handle: '5f7028e0bd5225c17b24bdaa0c09f914-8388085074acab7e91de633521be86f0', + title: 'Economy', + type: 'shipping', + }, + ], + }, + discountApplications: [], + discountsAmount: { + amount: 0, + currencyCode: 'USD', + }, + email: 'test-user@sampleemail.com', + lineItems: [ + { + discountAllocations: [], + finalLinePrice: { + amount: 1499.9, + currencyCode: 'USD', + }, + id: '41327143321713', + properties: [], + quantity: 2, + sellingPlanAllocation: null, + title: 'The Collection Snowboard: Liquid', + variant: { + id: '41327143321713', + image: { + src: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6_64x64.jpg?v=1724736600', + }, + price: { + amount: 749.95, + currencyCode: 'USD', + }, + product: { + id: '7234590834801', + title: 'The Collection Snowboard: Liquid', + type: 'snowboard', + untranslatedTitle: 'The Collection Snowboard: Liquid', + url: '/products/the-collection-snowboard-liquid', + vendor: 'Hydrogen Vendor', + }, + sku: null, + title: null, + untranslatedTitle: null, + }, + }, + { + discountAllocations: [], + finalLinePrice: { + amount: 1259.9, + currencyCode: 'USD', + }, + id: '41327143157873', + properties: [], + quantity: 2, + sellingPlanAllocation: null, + title: 'The Multi-managed Snowboard', + variant: { + id: '41327143157873', + image: { + src: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_9129b69a-0c7b-4f66-b6cf-c4222f18028a_64x64.jpg?v=1724736597', + }, + price: { + amount: 629.95, + currencyCode: 'USD', + }, + product: { + id: '7234590736497', + title: 'The Multi-managed Snowboard', + type: 'snowboard', + untranslatedTitle: 'The Multi-managed Snowboard', + url: '/products/the-multi-managed-snowboard', + vendor: 'Multi-managed Vendor', + }, + sku: 'sku-managed-1', + title: null, + untranslatedTitle: null, + }, + }, + ], + localization: { + country: { + isoCode: 'US', + }, + language: { + isoCode: 'en-US', + }, + market: { + handle: 'us', + id: 'gid://shopify/Market/23505895537', + }, + }, + order: { + customer: { + id: null, + isFirstOrder: null, + }, + id: null, + }, + phone: '', + shippingAddress: { + address1: 'Queens Center', + address2: null, + city: 'Elmhurst', + country: 'US', + countryCode: 'US', + firstName: 'test', + lastName: 'user', + phone: null, + province: 'NY', + provinceCode: 'NY', + zip: '11373', + }, + shippingLine: { + price: { + amount: 0, + currencyCode: 'USD', + }, + }, + smsMarketingPhone: null, + subtotalPrice: { + amount: 2759.8, + currencyCode: 'USD', + }, + token: '5f7028e0bd5225c17b24bdaa0c09f914', + totalPrice: { + amount: 2759.8, + currencyCode: 'USD', + }, + totalTax: { + amount: 0, + currencyCode: 'USD', + }, + transactions: [], + }); expect(message.context).toEqual({ userAgent: 'Mozilla/5.0' }); }); }); diff --git a/test/integrations/sources/shopify/pixelTestScenarios/CheckoutEventsTests.ts b/test/integrations/sources/shopify/pixelTestScenarios/CheckoutEventsTests.ts index 3381223317..ff1ea39ed1 100644 --- a/test/integrations/sources/shopify/pixelTestScenarios/CheckoutEventsTests.ts +++ b/test/integrations/sources/shopify/pixelTestScenarios/CheckoutEventsTests.ts @@ -342,17 +342,8 @@ export const pixelCheckoutEventsTestScenarios = [ properties: { products: [ { - discountAllocations: [], - id: '41327143321713', quantity: 2, - title: 'The Collection Snowboard: Liquid', variant: 'The Collection Snowboard: Liquid', - finalLinePrice: { - amount: 1499.9, - currencyCode: 'USD', - }, - sellingPlanAllocation: null, - properties: [], name: 'The Collection Snowboard: Liquid', image_url: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6_64x64.jpg?v=1724736600', @@ -786,21 +777,12 @@ export const pixelCheckoutEventsTestScenarios = [ SHOPIFY: true, }, type: 'track', - event: 'Checkout Completed', + event: 'Order Completed', properties: { products: [ { - discountAllocations: [], - id: '41327143321713', quantity: 2, - title: 'The Collection Snowboard: Liquid', variant: 'The Collection Snowboard: Liquid', - finalLinePrice: { - amount: 1499.9, - currencyCode: 'USD', - }, - sellingPlanAllocation: null, - properties: [], name: 'The Collection Snowboard: Liquid', image_url: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6_64x64.jpg?v=1724736600', @@ -812,17 +794,8 @@ export const pixelCheckoutEventsTestScenarios = [ brand: 'Hydrogen Vendor', }, { - discountAllocations: [], - id: '41327143157873', quantity: 2, - title: 'The Multi-managed Snowboard', variant: 'The Multi-managed Snowboard', - finalLinePrice: { - amount: 1259.9, - currencyCode: 'USD', - }, - sellingPlanAllocation: null, - properties: [], name: 'The Multi-managed Snowboard', image_url: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_9129b69a-0c7b-4f66-b6cf-c4222f18028a_64x64.jpg?v=1724736597', diff --git a/test/integrations/sources/shopify/pixelTestScenarios/ProductEventsTests.ts b/test/integrations/sources/shopify/pixelTestScenarios/ProductEventsTests.ts index b293bd46f9..46bd4f9615 100644 --- a/test/integrations/sources/shopify/pixelTestScenarios/ProductEventsTests.ts +++ b/test/integrations/sources/shopify/pixelTestScenarios/ProductEventsTests.ts @@ -170,27 +170,6 @@ export const pixelEventsTestScenarios = [ type: 'track', event: 'Product Viewed', properties: { - productVariant: { - price: { - amount: 749.95, - currencyCode: 'USD', - }, - product: { - title: 'The Collection Snowboard: Liquid', - vendor: 'Hydrogen Vendor', - id: '7234590834801', - untranslatedTitle: 'The Collection Snowboard: Liquid', - url: '/products/the-collection-snowboard-liquid', - type: 'snowboard', - }, - id: '41327143321713', - image: { - src: '//store.myshopify.com/cdn/shop/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6.jpg?v=1724736600', - }, - sku: '', - title: 'Default Title', - untranslatedTitle: 'Default Title', - }, product_id: '7234590834801', variant: 'The Collection Snowboard: Liquid', brand: 'Hydrogen Vendor', @@ -357,33 +336,6 @@ export const pixelEventsTestScenarios = [ properties: { products: [ { - cost: { - totalAmount: { - amount: 1259.9, - currencyCode: 'USD', - }, - }, - merchandise: { - price: { - amount: 629.95, - currencyCode: 'USD', - }, - product: { - title: 'The Multi-managed Snowboard', - vendor: 'Multi-managed Vendor', - id: '7234590736497', - untranslatedTitle: 'The Multi-managed Snowboard', - url: '/products/the-multi-managed-snowboard', - type: 'snowboard', - }, - id: '41327143157873', - image: { - src: '//store.myshopify.com/cdn/shop/files/Main_9129b69a-0c7b-4f66-b6cf-c4222f18028a.jpg?v=1724736597', - }, - sku: 'sku-managed-1', - title: 'Default Title', - untranslatedTitle: 'Default Title', - }, quantity: 2, product_id: '7234590736497', variant: 'The Multi-managed Snowboard', @@ -612,21 +564,7 @@ export const pixelEventsTestScenarios = [ products: [ { price: 10, - product: { - title: 'Gift Card', - vendor: 'Snowboard Vendor', - id: '7234590605425', - untranslatedTitle: 'Gift Card', - url: '/products/gift-card', - type: 'giftcard', - }, - id: '41327142895729', - image: { - src: '//store.myshopify.com/cdn/shop/files/gift_card.png?v=1724736596', - }, sku: '', - title: '$10', - untranslatedTitle: '$10', image_url: '//store.myshopify.com/cdn/shop/files/gift_card.png?v=1724736596', product_id: '7234590605425', @@ -638,21 +576,7 @@ export const pixelEventsTestScenarios = [ }, { price: 24.95, - product: { - title: 'Selling Plans Ski Wax', - vendor: 'pixel-testing-rs', - id: '7234590802033', - untranslatedTitle: 'Selling Plans Ski Wax', - url: '/products/selling-plans-ski-wax', - type: 'accessories', - }, - id: '41327143223409', - image: { - src: '//store.myshopify.com/cdn/shop/files/snowboard_wax.png?v=1724736599', - }, sku: '', - title: 'Selling Plans Ski Wax', - untranslatedTitle: 'Selling Plans Ski Wax', image_url: '//store.myshopify.com/cdn/shop/files/snowboard_wax.png?v=1724736599', product_id: '7234590802033', @@ -664,21 +588,7 @@ export const pixelEventsTestScenarios = [ }, { price: 2629.95, - product: { - title: 'The 3p Fulfilled Snowboard', - vendor: 'pixel-testing-rs', - id: '7234590703729', - untranslatedTitle: 'The 3p Fulfilled Snowboard', - url: '/products/the-3p-fulfilled-snowboard', - type: 'snowboard', - }, - id: '41327143125105', - image: { - src: '//store.myshopify.com/cdn/shop/files/Main_b9e0da7f-db89-4d41-83f0-7f417b02831d.jpg?v=1724736597', - }, sku: 'sku-hosted-1', - title: 'Default Title', - untranslatedTitle: 'Default Title', image_url: '//store.myshopify.com/cdn/shop/files/Main_b9e0da7f-db89-4d41-83f0-7f417b02831d.jpg?v=1724736597', product_id: '7234590703729', @@ -819,36 +729,6 @@ export const pixelEventsTestScenarios = [ type: 'track', event: 'Product Added', properties: { - cartLine: { - cost: { - totalAmount: { - amount: 749.95, - currencyCode: 'USD', - }, - }, - merchandise: { - id: '41327143321713', - image: { - src: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6.jpg?v=1724736600', - }, - price: { - amount: 749.95, - currencyCode: 'USD', - }, - product: { - id: '7234590834801', - title: 'The Collection Snowboard: Liquid', - vendor: 'Hydrogen Vendor', - type: 'snowboard', - untranslatedTitle: 'The Collection Snowboard: Liquid', - url: '/products/the-collection-snowboard-liquid?variant=41327143321713', - }, - sku: '', - title: null, - untranslatedTitle: null, - }, - quantity: 1, - }, image_url: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6.jpg?v=1724736600', price: 749.95, @@ -990,36 +870,6 @@ export const pixelEventsTestScenarios = [ type: 'track', event: 'Product Removed', properties: { - cartLine: { - cost: { - totalAmount: { - amount: 749.95, - currencyCode: 'USD', - }, - }, - merchandise: { - id: '41327143321713', - image: { - src: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6.jpg?v=1724736600', - }, - price: { - amount: 749.95, - currencyCode: 'USD', - }, - product: { - id: '7234590834801', - title: 'The Collection Snowboard: Liquid', - vendor: 'Hydrogen Vendor', - type: 'snowboard', - untranslatedTitle: 'The Collection Snowboard: Liquid', - url: '/products/the-collection-snowboard-liquid?variant=41327143321713', - }, - sku: '', - title: null, - untranslatedTitle: null, - }, - quantity: 1, - }, image_url: 'https://cdn.shopify.com/s/files/1/0590/2696/4593/files/Main_b13ad453-477c-4ed1-9b43-81f3345adfd6.jpg?v=1724736600', price: 749.95, From a0eb8e90d8dff3ae44800abfb23d59ed3dedc6fc Mon Sep 17 00:00:00 2001 From: Aanshi Lahoti <110057617+aanshi07@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:52:18 +0530 Subject: [PATCH 3/3] fix: endpoint fix for tune destination (#3833) * feat: endpoint fix for tune destination * chore: minor fix --- src/v0/destinations/tune/transform.js | 8 ++++++-- .../destinations/tune/processor/trackTestData.ts | 4 ++-- test/integrations/destinations/tune/router/data.ts | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/v0/destinations/tune/transform.js b/src/v0/destinations/tune/transform.js index 97dad0e3d3..8103b4d2dc 100644 --- a/src/v0/destinations/tune/transform.js +++ b/src/v0/destinations/tune/transform.js @@ -8,6 +8,8 @@ const { isNotEmpty, } = require('../../util'); +const getTuneEndpoint = (subdomain) => `https://${subdomain}.go2cloud.org/aff_l`; + const mapPropertiesWithNestedSupport = (msg, properties, mappings) => { const mappedObj = {}; // Create a new object for parameters Object.entries(mappings).forEach(([key, value]) => { @@ -26,7 +28,7 @@ const mapPropertiesWithNestedSupport = (msg, properties, mappings) => { }; const responseBuilder = (message, { Config }) => { - const { tuneEvents } = Config; // Extract tuneEvents from config + const { tuneEvents, subdomain } = Config; // Extract tuneEvents from config const { properties, event: messageEvent } = message; // Destructure properties and event from message // Find the relevant tune event based on the message's event name @@ -43,10 +45,12 @@ const responseBuilder = (message, { Config }) => { ...mapPropertiesWithNestedSupport(message, properties, advUniqueIdHashMap), }; + const endpoint = getTuneEndpoint(subdomain); + // Prepare the response const response = defaultRequestConfig(); response.params = params; // Set only the mapped params - response.endpoint = tuneEvent.url; // Use the user-defined URL + response.endpoint = endpoint; return response; } diff --git a/test/integrations/destinations/tune/processor/trackTestData.ts b/test/integrations/destinations/tune/processor/trackTestData.ts index c19ffdd84c..63178d0e33 100644 --- a/test/integrations/destinations/tune/processor/trackTestData.ts +++ b/test/integrations/destinations/tune/processor/trackTestData.ts @@ -20,12 +20,12 @@ const destination: Destination = { connectionMode: { web: 'cloud', }, + subdomain: 'demo', consentManagement: {}, oneTrustCookieCategories: {}, ketchConsentPurposes: {}, tuneEvents: [ { - url: 'https://demo.go2cloud.org/aff_l?offer_id=45&aff_id=1029', eventName: 'Product added', standardMapping: [ { to: 'aff_id', from: 'affId' }, @@ -89,7 +89,7 @@ export const trackTestdata: ProcessorTestData[] = [ { output: transformResultBuilder({ method: 'POST', - endpoint: 'https://demo.go2cloud.org/aff_l?offer_id=45&aff_id=1029', + endpoint: 'https://demo.go2cloud.org/aff_l', event: 'Product added', headers: {}, params: { diff --git a/test/integrations/destinations/tune/router/data.ts b/test/integrations/destinations/tune/router/data.ts index 65bfee4ade..f21714d058 100644 --- a/test/integrations/destinations/tune/router/data.ts +++ b/test/integrations/destinations/tune/router/data.ts @@ -15,12 +15,12 @@ const destination: Destination = { connectionMode: { web: 'cloud', }, + subdomain: 'demo', consentManagement: {}, oneTrustCookieCategories: {}, ketchConsentPurposes: {}, tuneEvents: [ { - url: 'https://demo.go2cloud.org/aff_l?offer_id=45&aff_id=1029', eventName: 'Product added', standardMapping: [ { to: 'aff_id', from: 'affId' }, @@ -92,7 +92,7 @@ export const data: RouterTestData[] = [ version: '1', type: 'REST', method: 'POST', - endpoint: 'https://demo.go2cloud.org/aff_l?offer_id=45&aff_id=1029', + endpoint: 'https://demo.go2cloud.org/aff_l', headers: {}, params: { security_token: '1123',