diff --git a/packages/browser-destinations/.npmrc b/packages/browser-destinations/.npmrc deleted file mode 100644 index 4c6c54c7da..0000000000 --- a/packages/browser-destinations/.npmrc +++ /dev/null @@ -1,5 +0,0 @@ -# Canonical IDs for the cloudfront distributions that will be serving browser destinations from S3 -prod_cdn_oai="a81d36a9a042396b69ea0081400a4c68041762d1a09943b24f65b879041df89a3dc77374aa705f5b2d035da7e12ce3da" -stage_cdn_oai="8105d109960ae15aa4b175b24d3b21259596258a1e2e8219842bde30eb11eee6969ea4de9e735ab487ba054cdaa880b7" -prod_custom_domain_oai="f5304a60592a83540a9a6254c1967d95df993f685a684dc8885bfa1a50735da3d9cf9752f489ba6f9fc552ab1af35797" -stage_custom_domain_oai="d0f4e4f9d150e887bf5f3d982fcc52b5195fd02371644cdc79f024dffc4ce59c525981f5639802c6081c9b770e6696f8" \ No newline at end of file diff --git a/packages/browser-destinations/README.md b/packages/browser-destinations/README.md deleted file mode 100644 index 4a3ef03f32..0000000000 --- a/packages/browser-destinations/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# Browser Destinations - -This package contains the implementations for browser destinations. - -# Glossary - -- Action: A method defined by the author of the destination that's linked to a Segment event. -- Plugin: A plugin is an action in AJS lingo. You can see the loaded plugins by typing `analytics.queue.plugins` in the browser's console. -- Subscription: A "way-in" into an action. For example: the `updateUser` action uses a subscription of the type `identify`. See the test section for more information. - -## Developing - -> NOTE: The shell commands mentioned below must be run with `browser-destinations` as root directory. Every command should be run using lerna. - -### Actions CLI - -See the [Actions CLI](https://github.com/segmentio/action-destinations#actions-cli) of the root directory of this repo to learn how to interact with the Actions CLI. Interacting with the actions CLI will allow you to create new destinations, actions and update your type definitions. - -### Types - -When updating the types inside of your actions remember to regenerate the types of your integration by running this command in the top level directory. - -``` -bin/run generate:types -``` - -### Manual testing - -You can use our Action Tester environment to test your browser actions: - -``` -./bin/run serve --directory ./packages/browser-destinations/destinations --browser -``` - -This will give you an option to pick a destination to work on, and then opens the action tester. You can also debug the code from Visual Studio Code. Goto VSCode Debug Tab, and select "Launch Action Tester Web" from the "RUN AND DEBUG" dropdown ( make sure you ran the above command first ). This will launch a new instance of Google Chrome, and allow you to run your code in debug mode. - -### Automated tests - -Running the test suite - -``` -yarn test -``` - -Running one file at the time - -``` -yarn jest destinations/PATH-TO-YOUR-DESTINATION/src/__tests__/index.test.ts -``` - -## Deploying - -Coming Soon - -## License - -MIT License - -Copyright (c) 2024 Segment - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -## Contributing - -All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. diff --git a/packages/browser-destinations/__tests__/window.test.ts b/packages/browser-destinations/__tests__/window.test.ts deleted file mode 100644 index b0fdea83f8..0000000000 --- a/packages/browser-destinations/__tests__/window.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import segmentUtilitiesDestination from '../destinations/segment-utilities-web/src/index' - -it('window object shouldnt be changed by actions core', async () => { - const windowBefore = Object.keys(window) - - // load a plugin that doesn't alter window object - const [plugin] = await segmentUtilitiesDestination({ - throttleWindow: 3000, - passThroughCount: 1, - subscriptions: [ - { - partnerAction: 'throttle', - name: 'Throttle', - enabled: true, - subscribe: 'type = "track"', - mapping: {} - } - ] - }) - - await plugin.load(Context.system(), {} as Analytics) - - const windowAfter = Object.keys(window) - - // window object shouldn't change as long as actions-core isn't changing it - expect(windowBefore.sort()).toEqual(windowAfter.sort()) -}) diff --git a/packages/browser-destinations/babel.config.js b/packages/browser-destinations/babel.config.js deleted file mode 100644 index e6ca207f46..0000000000 --- a/packages/browser-destinations/babel.config.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - env: { - test: { - presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], - plugins: ['@babel/plugin-transform-modules-commonjs', '@babel/plugin-proposal-class-properties'] - } - } -} diff --git a/packages/browser-destinations/destinations/1flow/README.md b/packages/browser-destinations/destinations/1flow/README.md deleted file mode 100644 index d1f3ce5580..0000000000 --- a/packages/browser-destinations/destinations/1flow/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# @segment/analytics-browser-actions-1flow - -The 1Flow browser action destination for use with @segment/analytics-next. - -## License - -MIT License - -Copyright (c) 2024 Segment - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -## Contributing - -All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. diff --git a/packages/browser-destinations/destinations/1flow/package.json b/packages/browser-destinations/destinations/1flow/package.json deleted file mode 100644 index 796094a856..0000000000 --- a/packages/browser-destinations/destinations/1flow/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-1flow", - "version": "1.29.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/1flow/src/1flow.ts b/packages/browser-destinations/destinations/1flow/src/1flow.ts deleted file mode 100644 index a7e07e105c..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/1flow.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck - -export function initScript({ projectApiKey }) { - //Set your APP_ID - const apiKey = projectApiKey - - const autoURLTracking = false - ;(function (w, o, s, t, k, a, r) { - ;(w._1flow = function (e, d, v) { - s(function () { - w._1flow(e, d, !v ? {} : v) - }, 5) - }), - (a = o.getElementsByTagName('head')[0]) - r = o.createElement('script') - r.async = 1 - r.setAttribute('data-api-key', k) - r.src = t - a.appendChild(r) - })(window, document, setTimeout, 'https://1flow.app/js/1flow.js', apiKey) -} diff --git a/packages/browser-destinations/destinations/1flow/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/1flow/src/__tests__/index.test.ts deleted file mode 100644 index cd839e0ed5..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/__tests__/index.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import _1FlowDestination from '../index' -import { _1Flow } from '../api' - -describe('_1Flow', () => { - beforeAll(() => { - jest.mock('@segment/browser-destination-runtime/load-script', () => ({ - loadScript: (_src: any, _attributes: any) => {} - })) - jest.mock('@segment/browser-destination-runtime/resolve-when', () => ({ - resolveWhen: (_fn: any, _timeout: any) => {} - })) - }) - test('it maps event parameters correctly to identify function ', async () => {}) -}) diff --git a/packages/browser-destinations/destinations/1flow/src/api.ts b/packages/browser-destinations/destinations/1flow/src/api.ts deleted file mode 100644 index fe3b0a7984..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/api.ts +++ /dev/null @@ -1,11 +0,0 @@ -type method = 'track' | 'identify' - -type _1FlowApi = { - richLinkProperties: string[] | undefined - activator: string | undefined - projectApiKey: string -} - -type _1FlowFunction = (method: method, ...args: unknown[]) => void - -export type _1flow = _1FlowFunction & _1FlowApi diff --git a/packages/browser-destinations/destinations/1flow/src/generated-types.ts b/packages/browser-destinations/destinations/1flow/src/generated-types.ts deleted file mode 100644 index ad85489880..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * This is the unique app_id for your 1Flow application, serving as the identifier for data storage and retrieval. This field is mandatory. - */ - projectApiKey: string -} diff --git a/packages/browser-destinations/destinations/1flow/src/identifyUser/__tests__/index.test.ts b/packages/browser-destinations/destinations/1flow/src/identifyUser/__tests__/index.test.ts deleted file mode 100644 index f080cf0579..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/identifyUser/__tests__/index.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import _1FlowDestination from '../../index' - -describe('identify', () => { - beforeAll(() => { - jest.mock('@segment/browser-destination-runtime/load-script', () => ({ - loadScript: (_src: any, _attributes: any) => {} - })) - jest.mock('@segment/browser-destination-runtime/resolve-when', () => ({ - resolveWhen: (_fn: any, _timeout: any) => {} - })) - }) - - test('it maps event parameters correctly to identify function ', async () => {}) -}) diff --git a/packages/browser-destinations/destinations/1flow/src/identifyUser/generated-types.ts b/packages/browser-destinations/destinations/1flow/src/identifyUser/generated-types.ts deleted file mode 100644 index 87e4058615..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/identifyUser/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for the user. - */ - userId?: string - /** - * The user's custom attributes. - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/1flow/src/identifyUser/index.ts b/packages/browser-destinations/destinations/1flow/src/identifyUser/index.ts deleted file mode 100644 index ca8d07e261..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/identifyUser/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import { _1flow } from '../api' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -const action: BrowserActionDefinition = { - title: 'Identify User', - description: 'Create or update a user in 1Flow.', - defaultSubscription: 'type = "identify"', - platform: 'web', - fields: { - userId: { - description: 'A unique identifier for the user.', - label: 'User ID', - type: 'string', - required: false, - default: { - '@path': '$.userId' - } - }, - traits: { - description: "The user's custom attributes.", - label: 'Custom Attributes', - type: 'object', - required: false, - defaultObjectUI: 'keyvalue', - default: { - '@path': '$.traits' - } - } - }, - perform: (_1flow, event) => { - const { userId, traits } = event.payload - _1flow('identify', userId, { - ...traits - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/1flow/src/index.ts b/packages/browser-destinations/destinations/1flow/src/index.ts deleted file mode 100644 index 5c5b4e1106..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/index.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import trackEvent from './trackEvent' -import { initScript } from './1flow' -import { _1flow } from './api' -import identifyUser from './identifyUser' -import { defaultValues } from '@segment/actions-core' -declare global { - interface Window { - _1flow: _1flow - } -} - -export const destination: BrowserDestinationDefinition = { - name: '1Flow Web (Actions)', - slug: 'actions-1flow', - mode: 'device', - description: 'Send analytics from Segment to 1Flow', - settings: { - projectApiKey: { - description: - 'This is the unique app_id for your 1Flow application, serving as the identifier for data storage and retrieval. This field is mandatory.', - label: 'Project API Key', - type: 'string', - required: true - } - }, - presets: [ - { - name: 'Track Event', - subscribe: 'type = "track"', - partnerAction: 'trackEvent', - mapping: defaultValues(trackEvent.fields), - type: 'automatic' - }, - { - name: 'Identify User', - subscribe: 'type = "identify"', - partnerAction: 'identifyUser', - mapping: defaultValues(identifyUser.fields), - type: 'automatic' - } - ], - - initialize: async ({ settings }, deps) => { - const projectApiKey = settings.projectApiKey - initScript({ projectApiKey }) - await deps.resolveWhen(() => Object.prototype.hasOwnProperty.call(window, '_1flow'), 100) - return window._1flow - }, - actions: { - trackEvent, - identifyUser - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/1flow/src/trackEvent/__tests__/index.test.ts b/packages/browser-destinations/destinations/1flow/src/trackEvent/__tests__/index.test.ts deleted file mode 100644 index 8564c31fea..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/trackEvent/__tests__/index.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import _1flowDestination from '../../index' - -describe('track', () => { - beforeAll(() => { - jest.mock('@segment/browser-destination-runtime/load-script', () => ({ - loadScript: (_src: any, _attributes: any) => {} - })) - jest.mock('@segment/browser-destination-runtime/resolve-when', () => ({ - resolveWhen: (_fn: any, _timeout: any) => {} - })) - }) - - test('it maps event parameters correctly to track function', async () => {}) -}) diff --git a/packages/browser-destinations/destinations/1flow/src/trackEvent/generated-types.ts b/packages/browser-destinations/destinations/1flow/src/trackEvent/generated-types.ts deleted file mode 100644 index 5c7fd1c746..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/trackEvent/generated-types.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The name of the event. - */ - event_name: string - /** - * A unique identifier for the user. - */ - userId?: string - /** - * An anonymous identifier for the user. - */ - anonymousId?: string - /** - * Information associated with the event - */ - properties?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/1flow/src/trackEvent/index.ts b/packages/browser-destinations/destinations/1flow/src/trackEvent/index.ts deleted file mode 100644 index e8a096058e..0000000000 --- a/packages/browser-destinations/destinations/1flow/src/trackEvent/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import { _1flow } from '../api' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -const action: BrowserActionDefinition = { - title: 'Track Event', - description: 'Submit an event to 1Flow.', - defaultSubscription: 'type = "track"', - platform: 'web', - fields: { - event_name: { - description: 'The name of the event.', - label: 'Event Name', - type: 'string', - required: true, - default: { - '@path': '$.event' - } - }, - userId: { - description: 'A unique identifier for the user.', - label: 'User ID', - type: 'string', - required: false, - default: { - '@path': '$.userId' - } - }, - anonymousId: { - description: 'An anonymous identifier for the user.', - label: 'Anonymous ID', - type: 'string', - required: false, - default: { - '@path': '$.anonymousId' - } - }, - properties: { - description: 'Information associated with the event', - label: 'Event Properties', - type: 'object', - required: false, - default: { - '@path': '$.properties' - } - } - }, - perform: (_1flow, event) => { - const { event_name, userId, anonymousId, properties } = event.payload - _1flow('track', event_name, { - userId: userId, - anonymousId: anonymousId, - properties: properties - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/1flow/tsconfig.json b/packages/browser-destinations/destinations/1flow/tsconfig.json deleted file mode 100644 index c2a7897afd..0000000000 --- a/packages/browser-destinations/destinations/1flow/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} diff --git a/packages/browser-destinations/destinations/adobe-target/package.json b/packages/browser-destinations/destinations/adobe-target/package.json deleted file mode 100644 index d3fb29d9bf..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-adobe-target", - "version": "1.47.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build-es": "tsc", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/adobe-target/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/adobe-target/src/__tests__/index.test.ts deleted file mode 100644 index 182cf59624..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/__tests__/index.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import adobeTarget, { destination } from '../index' -import { Subscription } from '@segment/browser-destination-runtime/types' - -describe('Adobe Target Web', () => { - test('can load ATJS', async () => { - const subscriptions: Subscription[] = [ - { - partnerAction: 'upsertProfile', - name: 'Upsert Profile', - enabled: true, - subscribe: 'type = "identify"', - mapping: {} - } - ] - const [event] = await adobeTarget({ - client_code: 'segmentexchangepartn', - admin_number: '10', - version: '2.8.0', - cookie_domain: 'segment.com', - mbox_name: 'target-global-mbox', - subscriptions - }) - - jest.spyOn(destination, 'initialize') - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - const scripts = window.document.querySelectorAll('script') - expect(scripts).toMatchInlineSnapshot(` - NodeList [ - , - ] - `) - }) -}) diff --git a/packages/browser-destinations/destinations/adobe-target/src/__tests__/utils.test.ts b/packages/browser-destinations/destinations/adobe-target/src/__tests__/utils.test.ts deleted file mode 100644 index 7d94613806..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/__tests__/utils.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { serializeProperties } from '../utils' - -describe('Utils', () => { - describe('serializeProperties', () => { - test('converts array properties to string', async () => { - const tags = ['leonardo', 'michelangelo', 'donatello', 'raphael'] - const properties = { - eventName: 'purchase', - total: 42.42, - item: 'car', - itemTags: tags - } - - expect(serializeProperties(properties)).toEqual({ - eventName: 'purchase', - total: 42.42, - item: 'car', - itemTags: '["leonardo","michelangelo","donatello","raphael"]' - }) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/adobe-target/src/generated-types.ts b/packages/browser-destinations/destinations/adobe-target/src/generated-types.ts deleted file mode 100644 index 62eb8e918d..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/generated-types.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * Your Adobe Target client code. To find your client code in Adobe Target, navigate to **Administration > Implementation**. The client code is shown at the top under Account Details. - */ - client_code: string - /** - * Your Adobe Target admin number. To find your admin number, please follow the instructions in [Adobe Docs](https://experienceleague.adobe.com/docs/target/using/implement-target/client-side/at-js-implementation/deploy-at-js/implementing-target-without-a-tag-manager.html). - */ - admin_number: string - /** - * The version of ATJS to use. Defaults to 2.8.0. - */ - version: string - /** - * The name of the Adobe Target mbox to use. Defaults to `target-global-mbox`. - */ - mbox_name: string - /** - * The domain from which you serve the mbox. Adobe Target recommends setting this value to your company's top-level domain. - */ - cookie_domain: string -} diff --git a/packages/browser-destinations/destinations/adobe-target/src/index.ts b/packages/browser-destinations/destinations/adobe-target/src/index.ts deleted file mode 100644 index 711ac38be3..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import { Adobe } from './types' -import { initScript } from './init-script' - -import upsertProfile from './upsertProfile' -import triggerView from './triggerView' -import trackEvent from './trackEvent' - -declare global { - interface Window { - adobe: Adobe - targetPageParams: Function - pageParams: Object - } -} - -export const destination: BrowserDestinationDefinition = { - name: 'Adobe Target Web', - slug: 'actions-adobe-target-web', - mode: 'device', - - settings: { - client_code: { - label: 'Client Code', - description: - 'Your Adobe Target client code. To find your client code in Adobe Target, navigate to **Administration > Implementation**. The client code is shown at the top under Account Details.', - required: true, - type: 'string' - }, - admin_number: { - label: 'Admin number', - description: - 'Your Adobe Target admin number. To find your admin number, please follow the instructions in [Adobe Docs](https://experienceleague.adobe.com/docs/target/using/implement-target/client-side/at-js-implementation/deploy-at-js/implementing-target-without-a-tag-manager.html).', - required: true, - type: 'string' - }, - version: { - label: 'ATJS Version', - description: 'The version of ATJS to use. Defaults to 2.8.0.', - type: 'string', - choices: [ - { - value: '2.8.0', - label: '2.8.0' - } - ], - default: '2.8.0', - required: true - }, - mbox_name: { - label: 'Mbox Name', - description: 'The name of the Adobe Target mbox to use. Defaults to `target-global-mbox`.', - type: 'string', - required: true, - default: 'target-global-mbox' - }, - cookie_domain: { - label: 'Cookie Domain', - description: - "The domain from which you serve the mbox. Adobe Target recommends setting this value to your company's top-level domain.", - type: 'string', - required: true - } - }, - - initialize: async ({ settings }, deps) => { - initScript(settings) - - const targetUrl = 'testandtarget.omniture.com/admin/rest/v1/libraries/atjs/download' - const atjsUrl = `https://admin${settings.admin_number}.${targetUrl}?client=${settings.client_code}&version=${settings.version}` - - await deps.loadScript(atjsUrl) - await deps.resolveWhen(() => Object.prototype.hasOwnProperty.call(window, 'adobe'), 100) - return window.adobe - }, - - actions: { - upsertProfile, - triggerView, - trackEvent - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/adobe-target/src/init-script.ts b/packages/browser-destinations/destinations/adobe-target/src/init-script.ts deleted file mode 100644 index 8e8272ac52..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/init-script.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck - -import { getPageParams } from './utils' - -export function initScript(settings) { - window.pageParams = {} - window.targetGlobalSettings = { - cookieDomain: settings.cookie_domain, - enabled: true - } - - // DO NOT RENAME. This function is required by Adobe Target. - // Learn More: https://experienceleague.adobe.com/docs/target/using/implement-target/client-side/at-js-implementation/functions-overview/targetpageparams.html?lang=en - window.targetPageParams = function () { - return getPageParams() - } -} diff --git a/packages/browser-destinations/destinations/adobe-target/src/trackEvent/__tests__/index.test.ts b/packages/browser-destinations/destinations/adobe-target/src/trackEvent/__tests__/index.test.ts deleted file mode 100644 index d70fcbe7bf..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/trackEvent/__tests__/index.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import adobeTarget, { destination } from '../../index' -import { Subscription } from '@segment/browser-destination-runtime/types' - -describe('Adobe Target Web', () => { - describe('#track', () => { - test('Calls track to track events', async () => { - const subscriptions: Subscription[] = [ - { - partnerAction: 'trackEvent', - name: 'Track Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - userId: { - '@if': { - exists: { - '@path': '$.userId' - }, - then: { - '@path': '$.userId' - }, - else: { - '@path': '$.anonymousId' - } - } - }, - type: { - '@path': '$.event' - }, - properties: { - '@path': '$.properties' - } - } - } - ] - - const targetSettings = { - client_code: 'segmentexchangepartn', - admin_number: '10', - version: '2.8.0', - cookie_domain: 'segment.com', - mbox_name: 'target-global-mbox' - } - - const trackParams = { - properties: { - purchase_amount: 42.21, - currency: 'USD', - item: 'Shirt' - } - } - - const [event] = await adobeTarget({ - ...targetSettings, - subscriptions - }) - - jest.spyOn(destination, 'initialize') - - destination.actions.trackEvent.perform = jest.fn(destination.actions.trackEvent.perform) - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - await event.track?.( - new Context({ - event: 'purchase', - type: 'track', - ...trackParams - }) - ) - - expect(destination.actions.trackEvent.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - ...trackParams, - type: 'purchase' - } - }) - ) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/adobe-target/src/trackEvent/generated-types.ts b/packages/browser-destinations/destinations/adobe-target/src/trackEvent/generated-types.ts deleted file mode 100644 index 0a9bc6b533..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/trackEvent/generated-types.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The event type. Please ensure the type entered here is registered and available. - */ - type?: string - /** - * This will be sent to Adobe Target as an event parameter called "event_name". - */ - eventName?: string - /** - * Parameters specific to the event. - */ - properties?: { - [k: string]: unknown - } - /** - * A user’s unique visitor ID. Setting an Mbox 3rd Party ID allows for updates via the Adobe Target Cloud Mode Destination. For more information, please see our Adobe Target Destination documentation. - */ - userId?: string -} diff --git a/packages/browser-destinations/destinations/adobe-target/src/trackEvent/index.ts b/packages/browser-destinations/destinations/adobe-target/src/trackEvent/index.ts deleted file mode 100644 index 933b24d601..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/trackEvent/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { Adobe } from '../types' -import { setMbox3rdPartyId, serializeProperties } from '../utils' - -// Adobe Target only takes certain event types as valid parameters. We are defaulting to "display". -// Beware of changing it since other event types drop the event properties from AT's audience builder. - -const TARGET_EVENT_TYPE = 'display' - -const action: BrowserActionDefinition = { - title: 'Track Event', - description: 'Send user actions, such as clicks and conversions, to Adobe Target.', - platform: 'web', - defaultSubscription: 'type = "track"', - fields: { - type: { - label: 'Event Type', - description: 'The event type. Please ensure the type entered here is registered and available.', - type: 'string', - default: TARGET_EVENT_TYPE - }, - eventName: { - label: 'Event Name', - description: 'This will be sent to Adobe Target as an event parameter called "event_name".', - type: 'string', - default: { - '@path': '$.event' - } - }, - properties: { - label: 'Event Parameters', - description: 'Parameters specific to the event.', - type: 'object', - default: { - '@path': '$.properties' - } - }, - userId: { - type: 'string', - description: - 'A user’s unique visitor ID. Setting an Mbox 3rd Party ID allows for updates via the Adobe Target Cloud Mode Destination. For more information, please see our Adobe Target Destination documentation.', - label: 'Mbox 3rd Party ID', - default: { - '@if': { - exists: { '@path': '$.userId' }, - then: { '@path': '$.userId' }, - else: { '@path': '$.anonymousId' } - } - } - } - }, - perform: (Adobe, event) => { - const payload = event.payload - setMbox3rdPartyId(payload.userId) - - const event_params = { - ...serializeProperties(payload.properties), - event_name: payload.eventName - } - - const params = { - mbox: event.settings.mbox_name, - preventDefault: true, - params: event_params, - type: payload.type - } - - Adobe.target.trackEvent(params) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/adobe-target/src/triggerView/__tests__/index.test.ts b/packages/browser-destinations/destinations/adobe-target/src/triggerView/__tests__/index.test.ts deleted file mode 100644 index 8f402c57a1..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/triggerView/__tests__/index.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import adobeTarget, { destination } from '../../index' -import { Subscription } from '@segment/browser-destination-runtime/types' - -describe('Adobe Target Web', () => { - describe('#page', () => { - test('tracks a view with the page() parameters', async () => { - const subscriptions: Subscription[] = [ - { - partnerAction: 'triggerView', - name: 'Trigger View', - enabled: true, - subscribe: 'type = "page"', - mapping: { - viewName: { '@path': '$.name' }, - pageParameters: { '@path': '$.properties' }, - sendNotification: true, - traits: { - '@path': '$.traits' - } - } - } - ] - - const targetSettings = { - client_code: 'segmentexchangepartn', - admin_number: '10', - version: '2.8.0', - cookie_domain: 'segment.com', - mbox_name: 'target-global-mbox' - } - - const pageParams = { - name: 'The Test Suite', - properties: { - language: 'ES', - currency: 'MXN', - region: { - country_code: 'MX', - state: 'Mich' - } - } - } - - const [event] = await adobeTarget({ - ...targetSettings, - subscriptions - }) - - jest.spyOn(destination, 'initialize') - - destination.actions.triggerView.perform = jest.fn(destination.actions.triggerView.perform) - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - await event.page?.( - new Context({ - type: 'page', - ...pageParams - }) - ) - - expect(destination.actions.triggerView.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - viewName: 'The Test Suite', - pageParameters: { - currency: 'MXN', - language: 'ES', - region: { country_code: 'MX', state: 'Mich' } - }, - sendNotification: true - } - }) - ) - - expect(window.pageParams).toEqual({ - page: { - language: 'ES', - currency: 'MXN', - region: { - country_code: 'MX', - state: 'Mich' - } - } - }) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/adobe-target/src/triggerView/generated-types.ts b/packages/browser-destinations/destinations/adobe-target/src/triggerView/generated-types.ts deleted file mode 100644 index 14e0876ee3..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/triggerView/generated-types.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * Name of the view or page. - */ - viewName: string - /** - * Parameters specific to the view or page. - */ - pageParameters?: { - [k: string]: unknown - } - /** - * By default, notifications are sent to the Adobe Target backend for incrementing impression count. If false, notifications are not sent for incrementing impression count. - */ - sendNotification?: boolean - /** - * A user’s unique visitor ID. Setting an Mbox 3rd Party ID allows for updates via the Adobe Target Cloud Mode Destination. For more information, please see our Adobe Target Destination documentation. - */ - userId?: string -} diff --git a/packages/browser-destinations/destinations/adobe-target/src/triggerView/index.ts b/packages/browser-destinations/destinations/adobe-target/src/triggerView/index.ts deleted file mode 100644 index 32822c88e4..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/triggerView/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { Adobe } from '../types' -import { setPageParams, setMbox3rdPartyId } from '../utils' - -const action: BrowserActionDefinition = { - title: 'Trigger View', - defaultSubscription: 'type = "page"', - description: 'Send page-level data to Adobe Target.', - platform: 'web', - fields: { - viewName: { - type: 'string', - description: 'Name of the view or page.', - label: 'View Name', - default: { - '@path': '$.name' - }, - required: true - }, - pageParameters: { - type: 'object', - description: 'Parameters specific to the view or page.', - label: 'Page Parameters', - default: { - '@path': '$.properties' - } - }, - sendNotification: { - type: 'boolean', - description: - 'By default, notifications are sent to the Adobe Target backend for incrementing impression count. If false, notifications are not sent for incrementing impression count. ', - label: 'Send Notifications to Adobe Target.', - default: true - }, - userId: { - type: 'string', - description: - 'A user’s unique visitor ID. Setting an Mbox 3rd Party ID allows for updates via the Adobe Target Cloud Mode Destination. For more information, please see our Adobe Target Destination documentation.', - label: 'Mbox 3rd Party ID', - default: { - '@if': { - exists: { '@path': '$.userId' }, - then: { '@path': '$.userId' }, - else: { '@path': '$.anonymousId' } - } - } - } - }, - perform: (Adobe, event) => { - const sendNotification = event.payload.sendNotification - const pageParams = event.payload.pageParameters - - setMbox3rdPartyId(event.payload.userId) - - /* - NOTE: - Page data needs to be set before the call to adobe.target.triggerView. - This is because the page data needs to be part of the global pageParams object. - */ - setPageParams({ page: { ...pageParams } }) - - Adobe.target.triggerView(event.payload.viewName, { page: sendNotification }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/adobe-target/src/types.ts b/packages/browser-destinations/destinations/adobe-target/src/types.ts deleted file mode 100644 index 82bb0d8152..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type Adobe = { - target: Target -} - -type Target = { - trackEvent: Function - triggerView: Function -} diff --git a/packages/browser-destinations/destinations/adobe-target/src/upsertProfile/__tests__/index.test.ts b/packages/browser-destinations/destinations/adobe-target/src/upsertProfile/__tests__/index.test.ts deleted file mode 100644 index cae03f0742..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/upsertProfile/__tests__/index.test.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import adobeTarget, { destination } from '../../index' -import { Subscription } from '@segment/browser-destination-runtime/types' - -describe('Adobe Target Web', () => { - describe('#identify', () => { - test('calls identify and simulates a login flow', async () => { - const subscriptions: Subscription[] = [ - { - partnerAction: 'upsertProfile', - name: 'Upsert Profile', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - userId: { - '@if': { - exists: { - '@path': '$.userId' - }, - then: { - '@path': '$.userId' - }, - else: { - '@path': '$.anonymousId' - } - } - }, - traits: { - '@path': '$.traits' - } - } - } - ] - - const targetSettings = { - client_code: 'segmentexchangepartn', - admin_number: '10', - version: '2.8.0', - cookie_domain: 'segment.com', - mbox_name: 'target-global-mbox' - } - - const identifyParams = { - traits: { - favorite_color: 'blue', - location: { - country_code: 'MX', - state: 'Mich' - } - } - } - - const [event] = await adobeTarget({ - ...targetSettings, - subscriptions - }) - - jest.spyOn(destination, 'initialize') - - destination.actions.upsertProfile.perform = jest.fn(destination.actions.upsertProfile.perform) - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - await event.identify?.( - new Context({ - anonymousId: 'random-id-42', - type: 'identify', - ...identifyParams - }) - ) - - expect(destination.actions.upsertProfile.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - userId: 'random-id-42', - traits: { - favorite_color: 'blue', - location: { - country_code: 'MX', - state: 'Mich' - } - } - } - }) - ) - - expect(window.pageParams).toEqual({ - mbox3rdPartyId: 'random-id-42', - profile: { - favorite_color: 'blue', - location: { - country_code: 'MX', - state: 'Mich' - } - } - }) - - await event.identify?.( - new Context({ - userId: 'The-Real-ID', - anonymousId: 'random-id-42', - type: 'identify', - ...identifyParams - }) - ) - - expect(destination.actions.upsertProfile.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - userId: 'The-Real-ID', - traits: { - favorite_color: 'blue', - location: { - country_code: 'MX', - state: 'Mich' - } - } - } - }) - ) - - expect(window.pageParams).toEqual({ - mbox3rdPartyId: 'The-Real-ID', - profile: { - favorite_color: 'blue', - location: { - country_code: 'MX', - state: 'Mich' - } - } - }) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/adobe-target/src/upsertProfile/generated-types.ts b/packages/browser-destinations/destinations/adobe-target/src/upsertProfile/generated-types.ts deleted file mode 100644 index 54896353f1..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/upsertProfile/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A user’s unique visitor ID. Setting an Mbox 3rd Party ID allows for updates via the Adobe Target Cloud Mode Destination. For more information, please see our Adobe Target Destination documentation. - */ - userId?: string - /** - * Profile parameters specific to a user. Please note, Adobe recommends that PII is hashed prior to sending to Adobe. - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/adobe-target/src/upsertProfile/index.ts b/packages/browser-destinations/destinations/adobe-target/src/upsertProfile/index.ts deleted file mode 100644 index 7a89e792a6..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/upsertProfile/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import { Adobe } from '../types' -import type { Payload } from './generated-types' -import { setPageParams, setMbox3rdPartyId } from '../utils' - -const action: BrowserActionDefinition = { - title: 'Upsert Profile', - description: 'Create or update a user profile in Adobe Target.', - platform: 'web', - defaultSubscription: 'type = "identify"', - fields: { - userId: { - type: 'string', - description: - 'A user’s unique visitor ID. Setting an Mbox 3rd Party ID allows for updates via the Adobe Target Cloud Mode Destination. For more information, please see our Adobe Target Destination documentation.', - label: 'Mbox 3rd Party ID', - default: { - '@if': { - exists: { '@path': '$.userId' }, - then: { '@path': '$.userId' }, - else: { '@path': '$.anonymousId' } - } - } - }, - traits: { - type: 'object', - description: - 'Profile parameters specific to a user. Please note, Adobe recommends that PII is hashed prior to sending to Adobe.', - label: 'Profile Attributes', - defaultObjectUI: 'keyvalue' - } - }, - perform: (Adobe, event) => { - /* - NOTE: - identify() and track() actions leverage the same function (adobe.target.trackEvent()) to send data to Adobe. - identify does not pass an event name, track does. - */ - setMbox3rdPartyId(event.payload.userId) - - /* - NOTE: - Profile data needs to be set before the call to adobe.target.trackEvent. - This is because the profile data needs to be part of the global pageParams object. - */ - setPageParams({ - profile: { - ...event.payload.traits - } - }) - - const params = { - mbox: event.settings.mbox_name, - params: { - event_name: 'profile_update' // DO NOT CHANGE. profile_update is used to differentiate between track and identify calls. - } - } - - Adobe.target.trackEvent(params) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/adobe-target/src/utils.ts b/packages/browser-destinations/destinations/adobe-target/src/utils.ts deleted file mode 100644 index f7a0056a7e..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/src/utils.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck - -export function getPageParams() { - return window.pageParams -} - -export function setPageParams(params) { - return (window.pageParams = { ...window.pageParams, ...params }) -} - -export function setMbox3rdPartyId(id) { - setPageParams({ mbox3rdPartyId: id }) -} - -// Track does not accept arrays as valid properties, therefore we are stringifying them. -export function serializeProperties(props: { [key: string]: unknown } | undefined) { - if (props === undefined) { - return {} - } - - const serialized: { [key: string]: unknown } = {} - - for (const key in props) { - serialized[key] = props[key] - if (Array.isArray(props[key])) { - serialized[key] = JSON.stringify(props[key]) - } - } - - return serialized -} diff --git a/packages/browser-destinations/destinations/adobe-target/tsconfig.json b/packages/browser-destinations/destinations/adobe-target/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/adobe-target/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/algolia-plugins/README.md b/packages/browser-destinations/destinations/algolia-plugins/README.md deleted file mode 100644 index a6d1391fd6..0000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# @segment/analytics-browser-actions-algolia-plugins - -The Algolia Plugins browser action destination for use with @segment/analytics-next. - -## License - -MIT License - -Copyright (c) 2023 Segment - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -## Contributing - -All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. diff --git a/packages/browser-destinations/destinations/algolia-plugins/package.json b/packages/browser-destinations/destinations/algolia-plugins/package.json deleted file mode 100644 index ba05073038..0000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-algolia-plugins", - "version": "1.24.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/algolia-plugins/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/algolia-plugins/src/__tests__/index.test.ts deleted file mode 100644 index 0ce3cffc05..0000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/src/__tests__/index.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Analytics, Context, Plugin } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime/types' -import browserPluginsDestination from '../' -import { queryIdIntegrationFieldName } from '../utils' - -const example: Subscription[] = [ - { - partnerAction: 'algoliaPlugin', - name: 'Algolia Plugin', - enabled: true, - subscribe: 'type = "track"', - mapping: {} - } -] - -let browserActions: Plugin[] -let algoliaPlugin: Plugin -let ajs: Analytics - -beforeEach(async () => { - browserActions = await browserPluginsDestination({ subscriptions: example }) - algoliaPlugin = browserActions[0] - - ajs = new Analytics({ - writeKey: 'w_123' - }) - Object.defineProperty(window, 'location', { - value: { - search: 'queryID=1234567' - }, - writable: true - }) -}) - -describe('ajs-integration', () => { - test('updates the original event with an Algolia query ID', async () => { - await algoliaPlugin.load(Context.system(), ajs) - - const ctx = new Context({ - type: 'track', - event: 'Test Event', - properties: { - greeting: 'Yo!' - } - }) - - const updatedCtx = await algoliaPlugin.track?.(ctx) - - const algoliaIntegrationsObj = updatedCtx?.event?.integrations['Algolia Insights (Actions)'] - expect(algoliaIntegrationsObj[queryIdIntegrationFieldName]).toEqual('1234567') - }) -}) diff --git a/packages/browser-destinations/destinations/algolia-plugins/src/algoliaPlugin/generated-types.ts b/packages/browser-destinations/destinations/algolia-plugins/src/algoliaPlugin/generated-types.ts deleted file mode 100644 index 944d22b085..0000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/src/algoliaPlugin/generated-types.ts +++ /dev/null @@ -1,3 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload {} diff --git a/packages/browser-destinations/destinations/algolia-plugins/src/algoliaPlugin/index.ts b/packages/browser-destinations/destinations/algolia-plugins/src/algoliaPlugin/index.ts deleted file mode 100644 index 86e8accaa8..0000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/src/algoliaPlugin/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { UniversalStorage } from '@segment/analytics-next' -import { storageFallback, storageQueryIdKey, queryIdIntegrationFieldName } from '../utils' - -const action: BrowserActionDefinition = { - title: 'Algolia Browser Plugin', - description: 'Enriches all Segment payloads with the Algolia query_id value', - platform: 'web', - hidden: false, - defaultSubscription: 'type = "track" or type = "identify" or type = "page" or type = "group" or type = "alias"', - fields: {}, - lifecycleHook: 'enrichment', - perform: (_, { context, analytics }) => { - const storage = (analytics.storage as UniversalStorage>) ?? storageFallback - - const query_id: string | null = storage.get(storageQueryIdKey) - - if (query_id && (context.event.integrations?.All !== false || context.event.integrations['Algolia Insights (Actions)'])) { - const integrationsData: Record = {} - integrationsData[queryIdIntegrationFieldName] = query_id - context.updateEvent(`integrations.Algolia Insights (Actions)`, integrationsData) - } - - return - } -} - -export default action diff --git a/packages/browser-destinations/destinations/algolia-plugins/src/generated-types.ts b/packages/browser-destinations/destinations/algolia-plugins/src/generated-types.ts deleted file mode 100644 index 1ceb7fa3b9..0000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/src/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * QueryString name you use for when storing the Algolia QueryID in a page URL. - */ - queryIdQueryStringName?: string -} diff --git a/packages/browser-destinations/destinations/algolia-plugins/src/index.ts b/packages/browser-destinations/destinations/algolia-plugins/src/index.ts deleted file mode 100644 index 12ac5288f6..0000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/src/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import { UniversalStorage } from '@segment/analytics-next' -import { storageFallback, storageQueryIdKey, queryIdQueryStringNameDefault } from './utils' - -import algoliaPlugin from './algoliaPlugin' - -// Switch from unknown to the partner SDK client types -export const destination: BrowserDestinationDefinition = { - name: 'Algolia Plugins', - slug: 'actions-algolia-plugins', - mode: 'device', - settings: { - queryIdQueryStringName: { - label: 'QueryID QueryString Name', - description: 'QueryString name you use for when storing the Algolia QueryID in a page URL.', - type: 'string', - default: queryIdQueryStringNameDefault, - required: false - } - }, - initialize: async ({ analytics, settings }) => { - const storage = (analytics.storage as UniversalStorage>) ?? storageFallback - - const urlParams = new URLSearchParams(window.location.search) - - const queryId: string | null = - urlParams.get(settings.queryIdQueryStringName ?? queryIdQueryStringNameDefault) || null - - if (queryId) { - storage.set(storageQueryIdKey, queryId) - } - - return {} - }, - actions: { - algoliaPlugin - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/algolia-plugins/src/utils.ts b/packages/browser-destinations/destinations/algolia-plugins/src/utils.ts deleted file mode 100644 index bb9ddb4b62..0000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/src/utils.ts +++ /dev/null @@ -1,17 +0,0 @@ -// The name of the storage location where we'll cache the Query ID value -export const storageQueryIdKey = 'analytics_algolia_query_id' - -export const queryIdQueryStringNameDefault = 'queryID' - -// The field name to include for the Algolia query_id in 'context.integrations.Algolia Insights (Actions)' -export const queryIdIntegrationFieldName = 'query_id' - -export const storageFallback = { - get: (key: string) => { - const data = window.localStorage.getItem(key) - return data - }, - set: (key: string, value: string) => { - return window.localStorage.setItem(key, value) - } -} diff --git a/packages/browser-destinations/destinations/algolia-plugins/tsconfig.json b/packages/browser-destinations/destinations/algolia-plugins/tsconfig.json deleted file mode 100644 index c2a7897afd..0000000000 --- a/packages/browser-destinations/destinations/algolia-plugins/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} diff --git a/packages/browser-destinations/destinations/amplitude-plugins/package.json b/packages/browser-destinations/destinations/amplitude-plugins/package.json deleted file mode 100644 index d9f62c51f9..0000000000 --- a/packages/browser-destinations/destinations/amplitude-plugins/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-amplitude-plugins", - "version": "1.47.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/amplitude-plugins/src/generated-types.ts b/packages/browser-destinations/destinations/amplitude-plugins/src/generated-types.ts deleted file mode 100644 index 4ab2786ec6..0000000000 --- a/packages/browser-destinations/destinations/amplitude-plugins/src/generated-types.ts +++ /dev/null @@ -1,3 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings {} diff --git a/packages/browser-destinations/destinations/amplitude-plugins/src/index.ts b/packages/browser-destinations/destinations/amplitude-plugins/src/index.ts deleted file mode 100644 index 9227d87747..0000000000 --- a/packages/browser-destinations/destinations/amplitude-plugins/src/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import sessionId from './sessionId' - -export const destination: BrowserDestinationDefinition = { - name: 'Amplitude (Actions)', - mode: 'device', - actions: { - sessionId - }, - initialize: async () => { - return {} - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/amplitude-plugins/src/sessionId/__tests__/sessionId.test.ts b/packages/browser-destinations/destinations/amplitude-plugins/src/sessionId/__tests__/sessionId.test.ts deleted file mode 100644 index dfd274d3ec..0000000000 --- a/packages/browser-destinations/destinations/amplitude-plugins/src/sessionId/__tests__/sessionId.test.ts +++ /dev/null @@ -1,358 +0,0 @@ -import { Analytics, Context, Plugin } from '@segment/analytics-next' -import browserPluginsDestination from '../..' -import { Subscription } from '@segment/browser-destination-runtime/types' -import jar from 'js-cookie' - -expect.extend({ - toBeWithinOneSecondOf(got, expected) { - if (typeof got === 'string') { - got = parseInt(got, 10) - } - - if (typeof expected === 'string') { - expected = parseInt(expected, 10) - } - - const oneSecond = 1000 - - const timeDiff = Math.abs(expected - got) - const timeDiffInSeconds = timeDiff / 1000 - - const pass = timeDiff < oneSecond - const message = () => - `${got} should be within a second of ${expected}, ` + `actual difference: ${timeDiffInSeconds.toFixed(1)}s` - - return { pass, message } - } -}) - -const example: Subscription[] = [ - { - partnerAction: 'sessionId', - name: 'SessionId', - enabled: true, - subscribe: 'type = "track"', - mapping: {} - } -] - -let browserActions: Plugin[] -let sessionIdPlugin: Plugin -let ajs: Analytics - -beforeEach(async () => { - browserActions = await browserPluginsDestination({ subscriptions: example }) - sessionIdPlugin = browserActions[0] - - // clear storage and cookies - document.cookie.split(';').forEach(function (c) { - document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/') - }) - window.localStorage.clear() - - ajs = new Analytics({ - writeKey: 'w_123' - }) -}) - -describe('ajs-integration', () => { - test('updates the original event with a session id', async () => { - await sessionIdPlugin.load(Context.system(), ajs) - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).not.toBeUndefined() - // @ts-expect-error - expect(typeof updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBe('number') - }) - - test('updates the original eveent when All: false but Actions Amplitude: true', async () => { - await sessionIdPlugin.load(Context.system(), ajs) - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - }, - integrations: { - All: false, - 'Actions Amplitude': true - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).not.toBeUndefined() - // @ts-expect-error - expect(typeof updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBe('number') - }) - - test('doesnt update the original event with a session id when All: false', async () => { - await sessionIdPlugin.load(Context.system(), ajs) - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - }, - integrations: { - All: false - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBeUndefined() - }) - - test('runs as an enrichment middleware', async () => { - await ajs.register(sessionIdPlugin) - jest.spyOn(sessionIdPlugin, 'track') - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - await ajs.track(ctx.event) - - expect(sessionIdPlugin.track).toHaveBeenCalled() - expect(ajs.queue.plugins.map((p) => ({ name: p.name, type: p.type }))).toMatchInlineSnapshot(` - Array [ - Object { - "name": "Amplitude (Actions) sessionId", - "type": "enrichment", - }, - ] - `) - }) -}) - -describe('sessionId', () => { - beforeEach(async () => { - jest.useFakeTimers('legacy') - await sessionIdPlugin.load(Context.system(), ajs) - }) - - const id = () => new Date().getTime() - - describe('new sessions', () => { - test('sets a session id', async () => { - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBeWithinOneSecondOf(id()) - }) - - test('persists the session id', async () => { - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - await sessionIdPlugin.track?.(ctx) - - // persists the session id in both cookies and local storage - expect(window.localStorage.getItem('analytics_session_id')).toBeWithinOneSecondOf(id().toString()) - expect(window.localStorage.getItem('analytics_session_id.last_access')).toBeWithinOneSecondOf(id().toString()) - expect(jar.get('analytics_session_id')).toBeWithinOneSecondOf(id().toString()) - expect(jar.get('analytics_session_id.last_access')).toBeWithinOneSecondOf(id().toString()) - expect(jar.get('analytics_session_id')).toBe(window.localStorage.getItem('analytics_session_id')) - expect(jar.get('analytics_session_id.last_access')).toBe(window.localStorage.getItem('analytics_session_id')) - }) - }) - - describe('existing sessions', () => { - test('uses an existing session id in LS', async () => { - const then = id() - jest.advanceTimersByTime(10000) - - window.localStorage.setItem('analytics_session_id', then.toString()) - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBeWithinOneSecondOf(then) - }) - - test('sync session info from LS to cookies', async () => { - const then = id() - - window.localStorage.setItem('analytics_session_id', then.toString()) - window.localStorage.setItem('analytics_session_id.last_access', then.toString()) - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBeWithinOneSecondOf(then) - expect(jar.get('analytics_session_id')).toBeWithinOneSecondOf(then) - }) - - test('uses an existing session id stored in cookies and sync it with local storage', async () => { - const then = id() - jest.advanceTimersByTime(10000) - jar.set('analytics_session_id', then.toString()) - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - const now = id() - const updatedCtx = await sessionIdPlugin.track?.(ctx) - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBeWithinOneSecondOf(then) - // synced to local storage - expect(window.localStorage.getItem('analytics_session_id.last_access')).toBeWithinOneSecondOf(now) - expect(window.localStorage.getItem('analytics_session_id')).toBeWithinOneSecondOf(then) - }) - - test('keeps track of when the session was last accessed', async () => { - const then = id() - jest.advanceTimersByTime(10000) - window.localStorage.setItem('analytics_session_id', then.toString()) - - const now = id() - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBeWithinOneSecondOf(then) - - expect(window.localStorage.getItem('analytics_session_id.last_access')).toBeWithinOneSecondOf(now) - expect(jar.get('analytics_session_id.last_access')).toBeWithinOneSecondOf(now) - }) - - test('reset session when stale', async () => { - const then = id() - window.localStorage.setItem('analytics_session_id.last_access', then.toString()) - window.localStorage.setItem('analytics_session_id', then.toString()) - - const THIRTY_MINUTES = 30 * 60000 - jest.advanceTimersByTime(THIRTY_MINUTES) - - const now = id() - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBeWithinOneSecondOf(now) - - expect(window.localStorage.getItem('analytics_session_id')).toBeWithinOneSecondOf(now.toString()) - expect(window.localStorage.getItem('analytics_session_id.last_access')).toBeWithinOneSecondOf(now.toString()) - expect(jar.get('analytics_session_id')).toBeWithinOneSecondOf(now.toString()) - expect(jar.get('analytics_session_id.last_access')).toBeWithinOneSecondOf(now.toString()) - }) - }) - - describe('work without AJS storage layer', () => { - test('uses an existing session id in LS when AJS storage layer is not available', async () => { - const then = id() - //@ts-expect-error - jest.spyOn(ajs, 'storage', 'get').mockReturnValue(undefined) - jest.advanceTimersByTime(10000) - - window.localStorage.setItem('analytics_session_id', then.toString()) - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBeWithinOneSecondOf(then) - expect(jar.get('analytics_session_id')).toBe(undefined) - }) - - test('uses an existing session id in LS when AJS storage layer is not available', async () => { - const then = id() - //@ts-expect-error - jest.spyOn(ajs, 'storage', 'get').mockReturnValue(undefined) - - window.localStorage.setItem('analytics_session_id.last_access', then.toString()) - window.localStorage.setItem('analytics_session_id', then.toString()) - - const THIRTY_MINUTES = 30 * 60000 - jest.advanceTimersByTime(THIRTY_MINUTES) - - const now = id() - - const ctx = new Context({ - type: 'track', - event: 'greet', - properties: { - greeting: 'Oi!' - } - }) - - const updatedCtx = await sessionIdPlugin.track?.(ctx) - // @ts-expect-error Need to fix ajs-next types to allow for complex objects in `integrations` - expect(updatedCtx?.event.integrations['Actions Amplitude']?.session_id).toBeWithinOneSecondOf(now) - - expect(window.localStorage.getItem('analytics_session_id')).toBeWithinOneSecondOf(now.toString()) - expect(window.localStorage.getItem('analytics_session_id.last_access')).toBeWithinOneSecondOf(now.toString()) - expect(jar.get('analytics_session_id')).toBeUndefined() - expect(jar.get('analytics_session_id.last_access')).toBeUndefined() - }) - }) -}) diff --git a/packages/browser-destinations/destinations/amplitude-plugins/src/sessionId/generated-types.ts b/packages/browser-destinations/destinations/amplitude-plugins/src/sessionId/generated-types.ts deleted file mode 100644 index 8ed67ee874..0000000000 --- a/packages/browser-destinations/destinations/amplitude-plugins/src/sessionId/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * Time in milliseconds to be used before considering a session stale. - */ - sessionLength?: number -} diff --git a/packages/browser-destinations/destinations/amplitude-plugins/src/sessionId/index.ts b/packages/browser-destinations/destinations/amplitude-plugins/src/sessionId/index.ts deleted file mode 100644 index 24aa9d8927..0000000000 --- a/packages/browser-destinations/destinations/amplitude-plugins/src/sessionId/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-call */ -import { UniversalStorage } from '@segment/analytics-next' -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -function newSessionId(): number { - return now() -} - -function now(): number { - return new Date().getTime() -} - -const THIRTY_MINUTES = 30 * 60000 - -function stale(id: number | null, updated: number | null, length: number = THIRTY_MINUTES): id is null { - if (id === null || updated === null) { - return true - } - - const accessedAt = updated - - if (now() - accessedAt >= length) { - return true - } - - return false -} - -const action: BrowserActionDefinition = { - title: 'Session Plugin', - description: 'Generates a Session ID and attaches it to every Amplitude browser based event.', - platform: 'web', - hidden: true, - defaultSubscription: 'type = "track" or type = "identify" or type = "group" or type = "page" or type = "alias"', - fields: { - sessionLength: { - label: 'Session Length', - type: 'number', - required: false, - description: 'Time in milliseconds to be used before considering a session stale.' - } - }, - lifecycleHook: 'enrichment', - perform: (_, { context, payload, analytics }) => { - // TODO: this can be removed when storage layer in AJS is rolled out to all customers - const storageFallback = { - get: (key: string) => { - const data = window.localStorage.getItem(key) - return data === null ? null : parseInt(data, 10) - }, - set: (key: string, value: number) => { - return window.localStorage.setItem(key, value.toString()) - } - } - - const newSession = newSessionId() - const storage = analytics.storage - ? // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - (analytics.storage as UniversalStorage>) - : storageFallback - - const raw = storage.get('analytics_session_id') - const updated = storage.get('analytics_session_id.last_access') - - let id: number | null = raw - if (stale(raw, updated, payload.sessionLength)) { - id = newSession - storage.set('analytics_session_id', id) - } else { - // we are storing the session id regardless, so it gets synced between different storage mediums - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- id can't be null because of stale check - storage.set('analytics_session_id', id!) - } - - storage.set('analytics_session_id.last_access', newSession) - - if (context.event.integrations?.All !== false || context.event.integrations['Actions Amplitude']) { - context.updateEvent('integrations.Actions Amplitude', {}) - context.updateEvent('integrations.Actions Amplitude.session_id', id) - } - - return - } -} - -export default action diff --git a/packages/browser-destinations/destinations/amplitude-plugins/tsconfig.json b/packages/browser-destinations/destinations/amplitude-plugins/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/amplitude-plugins/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/braze-cloud-plugins/package.json b/packages/browser-destinations/destinations/braze-cloud-plugins/package.json deleted file mode 100644 index 7f9b01aac9..0000000000 --- a/packages/browser-destinations/destinations/braze-cloud-plugins/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-braze-cloud-plugins", - "version": "1.50.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/analytics-browser-actions-braze": "^1.50.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/braze-cloud-plugins/src/debouncePlugin.types.ts b/packages/browser-destinations/destinations/braze-cloud-plugins/src/debouncePlugin.types.ts deleted file mode 100644 index 944d22b085..0000000000 --- a/packages/browser-destinations/destinations/braze-cloud-plugins/src/debouncePlugin.types.ts +++ /dev/null @@ -1,3 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload {} diff --git a/packages/browser-destinations/destinations/braze-cloud-plugins/src/generated-types.ts b/packages/browser-destinations/destinations/braze-cloud-plugins/src/generated-types.ts deleted file mode 100644 index 4ab2786ec6..0000000000 --- a/packages/browser-destinations/destinations/braze-cloud-plugins/src/generated-types.ts +++ /dev/null @@ -1,3 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings {} diff --git a/packages/browser-destinations/destinations/braze-cloud-plugins/src/index.ts b/packages/browser-destinations/destinations/braze-cloud-plugins/src/index.ts deleted file mode 100644 index cf21c7db4e..0000000000 --- a/packages/browser-destinations/destinations/braze-cloud-plugins/src/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import debouncePlugin from '@segment/analytics-browser-actions-braze/debounce' - -export const destination: BrowserDestinationDefinition = { - name: 'Braze Cloud Mode (Actions)', - mode: 'device', - - settings: { - // Add any Segment destination settings required here - }, - - initialize: async () => { - return {} - }, - - actions: { - // @ts-expect-error the types wont match because the Settings are very different (expected) - debouncePlugin - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/braze-cloud-plugins/tsconfig.json b/packages/browser-destinations/destinations/braze-cloud-plugins/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/braze-cloud-plugins/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/braze/package.json b/packages/browser-destinations/destinations/braze/package.json deleted file mode 100644 index b88d7868f4..0000000000 --- a/packages/browser-destinations/destinations/braze/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-braze", - "version": "1.50.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "exports": { - ".": { - "require": "./dist/cjs/index.js", - "import": "./dist/esm/index.js" - }, - "./debounce": { - "require": "./dist/cjs/debounce/index.js", - "import": "./dist/esm/debounce/index.js" - } - }, - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typesVersions": { - "*": { - "*": [ - "dist/esm/index.d.ts" - ], - "debounce": [ - "dist/esm/debounce/index.d.ts" - ] - } - }, - "typings": "./dist/esm", - "dependencies": { - "@braze/web-sdk": "npm:@braze/web-sdk@^4.1.0", - "@braze/web-sdk-v3": "npm:@braze/web-sdk@^3.5.1", - "@segment/actions-core": "^3.116.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/braze/src/__tests__/__snapshots__/initialization.test.ts.snap b/packages/browser-destinations/destinations/braze/src/__tests__/__snapshots__/initialization.test.ts.snap deleted file mode 100644 index 151ce7d4dd..0000000000 --- a/packages/browser-destinations/destinations/braze/src/__tests__/__snapshots__/initialization.test.ts.snap +++ /dev/null @@ -1,24 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`initialization can load braze: - NodeList [ - , - ] - 1`] = ` -NodeList [ - , -] -`; diff --git a/packages/browser-destinations/destinations/braze/src/__tests__/__snapshots__/integration.test.ts.snap b/packages/browser-destinations/destinations/braze/src/__tests__/__snapshots__/integration.test.ts.snap deleted file mode 100644 index 79a1da3492..0000000000 --- a/packages/browser-destinations/destinations/braze/src/__tests__/__snapshots__/integration.test.ts.snap +++ /dev/null @@ -1,96 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`loads different versions from CDN 3.0: - NodeList [ - , - ] - 1`] = ` -NodeList [ - , -] -`; - -exports[`loads different versions from CDN 3.1: - NodeList [ - , - ] - 1`] = ` -NodeList [ - , -] -`; - -exports[`loads different versions from CDN 3.5: - NodeList [ - , - ] - 1`] = ` -NodeList [ - , -] -`; - -exports[`loads different versions from CDN undefined version: - NodeList [ - , - ] - 1`] = ` -NodeList [ - , -] -`; diff --git a/packages/browser-destinations/destinations/braze/src/__tests__/__snapshots__/trackPurchase.test.ts.snap b/packages/browser-destinations/destinations/braze/src/__tests__/__snapshots__/trackPurchase.test.ts.snap deleted file mode 100644 index f32839fa49..0000000000 --- a/packages/browser-destinations/destinations/braze/src/__tests__/__snapshots__/trackPurchase.test.ts.snap +++ /dev/null @@ -1,97 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`reports products when present (v3.5) 1`] = ` -Array [ - "p_123", - 399, - "BGP", - 2, - Object { - "banana": "yellow", - "products": Array [ - Object { - "currency": "BGP", - "price": 399, - "product_id": "p_123", - "quantity": 2, - }, - Object { - "price": 0, - "product_id": "p_456", - }, - ], - }, -] -`; - -exports[`reports products when present (v3.5) 2`] = ` -Array [ - "p_456", - 0, - "USD", - 1, - Object { - "banana": "yellow", - "products": Array [ - Object { - "currency": "BGP", - "price": 399, - "product_id": "p_123", - "quantity": 2, - }, - Object { - "price": 0, - "product_id": "p_456", - }, - ], - }, -] -`; - -exports[`reports products when present (v4.1) 1`] = ` -Array [ - "p_123", - 399, - "BGP", - 2, - Object { - "banana": "yellow", - "products": Array [ - Object { - "currency": "BGP", - "price": 399, - "product_id": "p_123", - "quantity": 2, - }, - Object { - "price": 0, - "product_id": "p_456", - }, - ], - }, -] -`; - -exports[`reports products when present (v4.1) 2`] = ` -Array [ - "p_456", - 0, - "USD", - 1, - Object { - "banana": "yellow", - "products": Array [ - Object { - "currency": "BGP", - "price": 399, - "product_id": "p_123", - "quantity": 2, - }, - Object { - "price": 0, - "product_id": "p_456", - }, - ], - }, -] -`; diff --git a/packages/browser-destinations/destinations/braze/src/__tests__/debounce.test.ts b/packages/browser-destinations/destinations/braze/src/__tests__/debounce.test.ts deleted file mode 100644 index e29b79af8e..0000000000 --- a/packages/browser-destinations/destinations/braze/src/__tests__/debounce.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import brazeDestination from '../index' - -let ajs: Analytics - -describe('debounce', () => { - beforeEach(async () => { - ajs = new Analytics({ - writeKey: 'w_123' - }) - }) - - test('changes the integration object', async () => { - const [debounce] = await brazeDestination({ - api_key: 'b_123', - endpoint: 'endpoint', - doNotLoadFontAwesome: true, - sdkVersion: '3.5', - subscriptions: [ - { - partnerAction: 'debounce', - name: 'Debounce', - enabled: true, - subscribe: 'type = "identify"', - mapping: {} - } - ] - }) - - await debounce.load(Context.system(), ajs) - const ctx = await debounce.identify?.( - new Context({ - type: 'identify', - userId: 'hasbulla', - anonymousId: 'the goat', - traits: {} - }) - ) - - expect(ctx.event.integrations['Braze Web Mode (Actions)']).toBe(true) - }) - - test('does not send the event to braze if IDs are the same', async () => { - const [debounce] = await brazeDestination({ - api_key: 'b_123', - endpoint: 'endpoint', - doNotLoadFontAwesome: true, - sdkVersion: '3.5', - subscriptions: [ - { - partnerAction: 'debounce', - name: 'Debounce', - enabled: true, - subscribe: 'type = "identify"', - mapping: {} - } - ] - }) - - await ajs.register(debounce) - - const ctx = await ajs.identify('hasbulla', { - goat: true - }) - expect(ctx.event.integrations['Braze Web Mode (Actions)']).toBe(true) - - const secondCtx = await ajs.identify('hasbulla', { - goat: true - }) - expect(secondCtx.event.integrations['Braze Web Mode (Actions)']).toBe(false) - }) - - test('ignores blank anonymous ids', async () => { - const [debounce] = await brazeDestination({ - api_key: 'b_123', - endpoint: 'endpoint', - doNotLoadFontAwesome: true, - sdkVersion: '4.1', - subscriptions: [ - { - partnerAction: 'debounce', - name: 'Debounce', - enabled: true, - subscribe: 'type = "identify"', - mapping: {} - } - ] - }) - - await ajs.register(debounce) - - const ctx = await ajs.identify() - expect(ctx.event.integrations['Braze Web Mode (Actions)']).toBe(true) - - const secondCtx = await ajs.identify() - expect(secondCtx.event.integrations['Braze Web Mode (Actions)']).toBe(false) - }) - - test('send events on trait changes', async () => { - const [debounce] = await brazeDestination({ - api_key: 'b_123', - endpoint: 'endpoint', - doNotLoadFontAwesome: true, - sdkVersion: '4.1', - subscriptions: [ - { - partnerAction: 'debounce', - name: 'Debounce', - enabled: true, - subscribe: 'type = "identify"', - mapping: {} - } - ] - }) - - await ajs.register(debounce) - - const ctx = await ajs.identify('hasbulla', { - goat: true - }) - expect(ctx.event.integrations['Braze Web Mode (Actions)']).toBe(true) - - const sameCtx = await ajs.identify('hasbulla', { - goat: true - }) - expect(sameCtx.event.integrations['Braze Web Mode (Actions)']).toBe(false) - - const changedTraits = await ajs.identify('hasbulla', { - weight: 'feather' - }) - expect(changedTraits.event.integrations['Braze Web Mode (Actions)']).toBe(true) - }) -}) diff --git a/packages/browser-destinations/destinations/braze/src/__tests__/initialization.test.ts b/packages/browser-destinations/destinations/braze/src/__tests__/initialization.test.ts deleted file mode 100644 index f2cdfa1c4e..0000000000 --- a/packages/browser-destinations/destinations/braze/src/__tests__/initialization.test.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime' -import brazeDestination, { destination } from '../index' - -describe('initialization', () => { - const settings = { - safariWebsitePushId: 'safari', - allowCrawlerActivity: true, - doNotLoadFontAwesome: true, - enableLogging: false, - localization: 'pt', - minimumIntervalBetweenTriggerActionsInSeconds: 60, - openInAppMessagesInNewTab: true, - sessionTimeoutInSeconds: 60, - requireExplicitInAppMessageDismissal: true, - allowUserSuppliedJavascript: true, - contentSecurityNonce: 'bar', - endpoint: 'endpoint', - sdkVersion: '3.5' - } - - beforeEach(async () => { - jest.restoreAllMocks() - jest.resetAllMocks() - }) - - test('can load braze', async () => { - const [event] = await brazeDestination({ - api_key: 'b_123', - subscriptions: [ - { - partnerAction: 'trackPurchase', - name: 'Log Custom Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - eventName: { - '@path': '$.event' - }, - eventProperties: { - '@path': '$.properties' - } - } - } - ], - ...settings - }) - - jest.spyOn(destination.actions.trackPurchase, 'perform') - jest.spyOn(destination, 'initialize') - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - const ctx = await event.track?.( - new Context({ - type: 'track', - properties: { - banana: '📞' - } - }) - ) - - expect(destination.actions.trackPurchase.perform).toHaveBeenCalled() - expect(ctx).not.toBeUndefined() - - const scripts = window.document.querySelectorAll('script') - - expect(scripts).toMatchSnapshot(` - NodeList [ - , - ] - `) - }) - - test('can defer braze initialization when deferUntilIdentified is on', async () => { - const [updateUserProfile, trackEvent] = await brazeDestination({ - api_key: 'b_123', - deferUntilIdentified: true, - subscriptions: destination.presets?.map((sub) => ({ ...sub, enabled: true })) as Subscription[], - ...settings - }) - - jest.spyOn(destination.actions.trackEvent, 'perform') - const initializeSpy = jest.spyOn(destination, 'initialize') - - const analytics = new Analytics({ writeKey: '123' }) - - await analytics.register(updateUserProfile, trackEvent) - - // Spy on the braze APIs now that braze has been loaded. - const { instance: braze } = await initializeSpy.mock.results[0].value - const openSessionSpy = jest.spyOn(braze, 'openSession') - const logCustomEventSpy = jest.spyOn(braze, 'logCustomEvent') - - await analytics.track?.({ - type: 'track', - event: 'UFC', - properties: { - goat: 'hasbulla' - } - }) - - expect(destination.actions.trackEvent.perform).toHaveBeenCalledWith( - expect.objectContaining({ - instance: expect.objectContaining({ - logCustomEvent: expect.any(Function) - }) - }), - - expect.objectContaining({ - payload: { eventName: 'UFC', eventProperties: { goat: 'hasbulla' } } - }) - ) - - expect(analytics.user().id()).toBe(null) - expect(openSessionSpy).not.toHaveBeenCalled() - expect(logCustomEventSpy).not.toHaveBeenCalled() - - await analytics.identify('27413') - - await analytics.track?.({ - type: 'track', - event: 'FIFA', - properties: { - goat: 'deno' - } - }) - - expect(openSessionSpy).toHaveBeenCalled() - expect(logCustomEventSpy).toHaveBeenCalledWith('FIFA', { goat: 'deno' }) - }) -}) diff --git a/packages/browser-destinations/destinations/braze/src/__tests__/integration.test.ts b/packages/browser-destinations/destinations/braze/src/__tests__/integration.test.ts deleted file mode 100644 index bc8225eff9..0000000000 --- a/packages/browser-destinations/destinations/braze/src/__tests__/integration.test.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import braze, { destination } from '..' -import type { Subscription } from '@segment/browser-destination-runtime/types' - -const example: Subscription[] = [ - { - partnerAction: 'trackEvent', - name: 'Log Custom Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - name: { - '@path': '$.name' - }, - properties: { - '@path': '$.properties' - } - } - } -] - -test('can load braze', async () => { - const [trackEvent] = await braze({ - api_key: 'api_key', - endpoint: 'sdk.iad-01.braze.com', - subscriptions: example, - doNotLoadFontAwesome: true, - sdkVersion: '3.5' - }) - - jest.spyOn(destination.actions.trackEvent, 'perform') - jest.spyOn(destination, 'initialize') - - await trackEvent.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - const ctx = await trackEvent.track?.( - new Context({ - type: 'track', - properties: { - banana: '📞' - } - }) - ) - - expect(destination.actions.trackEvent.perform).toHaveBeenCalled() - expect(ctx).not.toBeUndefined() -}) - -describe('loads different versions from CDN', () => { - test('3.0', async () => { - const [trackEvent] = await braze({ - api_key: 'api_key', - endpoint: 'sdk.iad-01.braze.com', - sdkVersion: '3.0', - doNotLoadFontAwesome: true, - subscriptions: example - }) - - await trackEvent.load(Context.system(), {} as Analytics) - - const scripts = window.document.querySelectorAll('script') - expect(scripts).toMatchSnapshot(` - NodeList [ - , - ] - `) - }) - - test('3.1', async () => { - const [trackEvent] = await braze({ - api_key: 'api_key', - endpoint: 'sdk.iad-01.braze.com', - sdkVersion: '3.1', - doNotLoadFontAwesome: true, - subscriptions: example - }) - - await trackEvent.load(Context.system(), {} as Analytics) - - const scripts = window.document.querySelectorAll('script') - // loads the service worker - expect(scripts).toMatchSnapshot(` - NodeList [ - , - ] - `) - }) - - test('3.5', async () => { - const [trackEvent] = await braze({ - api_key: 'api_key', - endpoint: 'sdk.iad-01.braze.com', - sdkVersion: '3.5', - doNotLoadFontAwesome: true, - subscriptions: example - }) - - await trackEvent.load(Context.system(), {} as Analytics) - - const scripts = window.document.querySelectorAll('script') - // loads the service worker - expect(scripts).toMatchSnapshot(` - NodeList [ - , - ] - `) - }) - - test('undefined version', async () => { - //@ts-expect-error sdkVersion is expected but undefined - const [trackEvent] = await braze({ - api_key: 'api_key', - endpoint: 'sdk.iad-01.braze.com', - doNotLoadFontAwesome: true, - subscriptions: example - }) - - await trackEvent.load(Context.system(), {} as Analytics) - - const scripts = window.document.querySelectorAll('script') - // loads the service worker - expect(scripts).toMatchSnapshot(` - NodeList [ - , - ] - `) - }) -}) diff --git a/packages/browser-destinations/destinations/braze/src/__tests__/trackEvent.test.ts b/packages/browser-destinations/destinations/braze/src/__tests__/trackEvent.test.ts deleted file mode 100644 index 6144726c07..0000000000 --- a/packages/browser-destinations/destinations/braze/src/__tests__/trackEvent.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import brazeDestination, { destination } from '../index' -const testSdkVersions = ['3.5', '4.1'] - -testSdkVersions.forEach((sdkVersion) => { - describe(`trackEvent (v${sdkVersion})`, () => { - test('invokes braze`s logCustomEvent API', async () => { - const [trackEvent] = await brazeDestination({ - api_key: 'b_123', - endpoint: 'endpoint', - sdkVersion, - doNotLoadFontAwesome: true, - subscriptions: [ - { - partnerAction: 'trackEvent', - name: 'Log Custom Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - eventName: { - '@path': '$.event' - }, - eventProperties: { - '@path': '$.properties' - } - } - } - ] - }) - - jest.spyOn(destination.actions.trackEvent, 'perform') - const initializeSpy = jest.spyOn(destination, 'initialize') - - await trackEvent.load(Context.system(), new Analytics({ writeKey: '123' })) - - // Spy on the braze APIs now that braze has been loaded. - const { instance: braze } = await initializeSpy.mock.results[0].value - const logCustomEventSpy = jest.spyOn(braze, 'logCustomEvent') - - await trackEvent.track?.( - new Context({ - type: 'track', - event: 'UFC', - properties: { - goat: 'hasbulla' - } - }) - ) - - expect(destination.actions.trackEvent.perform).toHaveBeenCalledWith( - expect.objectContaining({ - instance: expect.objectContaining({ - logCustomEvent: expect.any(Function) - }) - }), - - expect.objectContaining({ - payload: { eventName: 'UFC', eventProperties: { goat: 'hasbulla' } } - }) - ) - - expect(logCustomEventSpy).toHaveBeenCalledWith('UFC', { goat: 'hasbulla' }) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/braze/src/__tests__/trackPurchase.test.ts b/packages/browser-destinations/destinations/braze/src/__tests__/trackPurchase.test.ts deleted file mode 100644 index 036449b3c2..0000000000 --- a/packages/browser-destinations/destinations/braze/src/__tests__/trackPurchase.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import brazeDestination, { destination } from '../index' - -const testSdkVersions = ['3.5', '4.1'] - -testSdkVersions.forEach((sdkVersion) => { - test(`reports products when present (v${sdkVersion})`, async () => { - const initializeSpy = jest.spyOn(destination, 'initialize') - - const [trackPurchase] = await brazeDestination({ - api_key: 'b_123', - endpoint: 'endpoint', - sdkVersion, - doNotLoadFontAwesome: true, - subscriptions: [ - { - partnerAction: 'trackPurchase', - name: 'Log Purchase', - enabled: true, - subscribe: 'type = "track"', - mapping: { - purchaseProperties: { - '@path': '$.properties' - }, - products: { - '@path': '$.properties.products' - } - } - } - ] - }) - - await trackPurchase.load(Context.system(), new Analytics({ writeKey: '123' })) - - // Spy on the braze APIs now that braze has been loaded. - const { instance: braze } = await initializeSpy.mock.results[0].value - const brazeLogPurchase = jest.spyOn(braze, 'logPurchase').mockReturnValue(true) - - await trackPurchase.track?.( - new Context({ - type: 'track', - properties: { - banana: 'yellow', - products: [ - { - product_id: 'p_123', - price: 399, - currency: 'BGP', - quantity: 2 - }, - { - product_id: 'p_456', - price: 0 - } - ] - } - }) - ) - - expect(brazeLogPurchase.mock.calls[0]).toMatchSnapshot() - - // applying defaults - expect(brazeLogPurchase.mock.calls[1]).toMatchSnapshot() - }) -}) diff --git a/packages/browser-destinations/destinations/braze/src/__tests__/updateUserProfile.test.ts b/packages/browser-destinations/destinations/braze/src/__tests__/updateUserProfile.test.ts deleted file mode 100644 index 1eb970d8d7..0000000000 --- a/packages/browser-destinations/destinations/braze/src/__tests__/updateUserProfile.test.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import brazeDestination, { destination } from '../index' - -describe('updateUserProfile', () => { - const subscriptions = [ - { - partnerAction: 'updateUserProfile', - name: 'Update User Profile', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - country: { '@path': '$.traits.country' }, - current_location: { '@path': '$.traits.current_location' }, - custom_attributes: { '@path': '$.traits.custom_attributes' }, - dob: { '@path': '$.traits.dob' }, - email: { '@path': '$.traits.email' }, - email_subscribe: { '@path': '$.traits.email_subscribe' }, - first_name: { '@path': '$.traits.first_name' }, - gender: { '@path': '$.traits.gender' }, - home_city: { '@path': '$.traits.home_city' }, - image_url: { '@path': '$.traits.image_url' }, - language: { '@path': '$.traits.language' }, - last_name: { '@path': '$.traits.last_name' }, - phone: { '@path': '$.traits.phone' }, - push_subscribe: { '@path': '$.traits.push_subscribe' }, - subscription_groups: { '@path': '$.traits.braze_subscription_groups' } - } - } - ] - - beforeEach(async () => { - destination.actions.updateUserProfile.perform = jest.fn() - jest.spyOn(destination.actions.trackEvent, 'perform') - jest.spyOn(destination, 'initialize') - }) - - test('changes the external_id when present', async () => { - // @ts-expect-error all integrations seem to have this typescript error? - const [event] = await brazeDestination({ - api_key: 'b_123', - endpoint: 'endpoint', - sdkVersion: '3.5', - doNotLoadFontAwesome: true, - subscriptions: [ - { - partnerAction: 'updateUserProfile', - name: 'Log User', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - external_id: { - '@path': '$.traits.external_id' - } - } - } - ] - }) - - await event.load(Context.system(), new Analytics({ writeKey: '123' })) - await event.identify?.( - new Context({ - type: 'identify', - traits: { - external_id: 'xt_123' - } - }) - ) - - expect(destination.actions.updateUserProfile.perform).toHaveBeenCalledWith( - expect.objectContaining({ - instance: expect.objectContaining({ - changeUser: expect.any(Function) - }) - }), - - expect.objectContaining({ - payload: { external_id: 'xt_123' } - }) - ) - }) - - test('can change user traits', async () => { - const [event] = await brazeDestination({ - api_key: 'b_123', - endpoint: 'endpoint', - sdkVersion: '3.5', - doNotLoadFontAwesome: true, - subscriptions - }) - - await event.load(Context.system(), {} as Analytics) - await event.identify?.( - new Context({ - type: 'identify', - traits: { - external_id: 'xt_123', - country: 'BRA', - current_location: { - latitude: -23.54, - longitude: -46.65 - }, - custom_attributes: { - greeting: 'oi' - }, - dob: '01/01/2000', - email: 'foo@example.org', - email_subscribe: true, - first_name: 'Foo', - gender: 'M', - home_city: 'Miami', - image_url: 'img_url', - language: 'english', - last_name: 'Bar', - phone: '555 5555', - push_subscribe: true - } - }) - ) - - expect(destination.actions.updateUserProfile.perform).toHaveBeenCalledWith( - expect.objectContaining({ - instance: expect.objectContaining({ - changeUser: expect.any(Function) - }) - }), - - expect.objectContaining({ - payload: { - country: 'BRA', - current_location: { latitude: -23.54, longitude: -46.65 }, - custom_attributes: { greeting: 'oi' }, - dob: '01/01/2000', - email: 'foo@example.org', - email_subscribe: true, - first_name: 'Foo', - gender: 'M', - home_city: 'Miami', - image_url: 'img_url', - language: 'english', - last_name: 'Bar', - phone: '555 5555', - push_subscribe: true - } - }) - ) - }) - - test('sets subscription groups not as custom attributes', async () => { - const [event] = await brazeDestination({ - api_key: 'b_123', - endpoint: 'endpoint', - sdkVersion: '3.5', - doNotLoadFontAwesome: true, - subscriptions - }) - - await event.load(Context.system(), {} as Analytics) - - const braze_subscription_groups = [ - { - subscription_group_id: '5ertykiuyfjyttgkf', - subscription_group_state: 'unsubscribed' - }, - { - subscription_group_id: 'ytghkuguymjghb', - subscription_group_state: 'unsubscribed' - } - ] - await event.identify?.( - new Context({ - type: 'identify', - traits: { - dob: '01/01/2000', - braze_subscription_groups: braze_subscription_groups, - custom_attributes: { foo: 'bar' } - } - }) - ) - - expect(destination.actions.updateUserProfile.perform).toHaveBeenCalledWith( - expect.objectContaining({ - instance: expect.objectContaining({ - changeUser: expect.any(Function) - }) - }), - expect.objectContaining({ - payload: { - dob: '01/01/2000', - subscription_groups: braze_subscription_groups, - custom_attributes: { foo: 'bar' } - } - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/braze/src/braze-types.ts b/packages/browser-destinations/destinations/braze/src/braze-types.ts deleted file mode 100644 index 1f2532f85c..0000000000 --- a/packages/browser-destinations/destinations/braze/src/braze-types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type braze from '@braze/web-sdk' -import type appboy from '@braze/web-sdk-v3' - -export type BrazeType = typeof braze | typeof appboy - -export type BrazeDestinationClient = { - instance: BrazeType - ready: () => boolean -} diff --git a/packages/browser-destinations/destinations/braze/src/debounce/generated-types.ts b/packages/browser-destinations/destinations/braze/src/debounce/generated-types.ts deleted file mode 100644 index 944d22b085..0000000000 --- a/packages/browser-destinations/destinations/braze/src/debounce/generated-types.ts +++ /dev/null @@ -1,3 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload {} diff --git a/packages/browser-destinations/destinations/braze/src/debounce/index.ts b/packages/browser-destinations/destinations/braze/src/debounce/index.ts deleted file mode 100644 index 4cbebb00b9..0000000000 --- a/packages/browser-destinations/destinations/braze/src/debounce/index.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { BrazeDestinationClient } from '../braze-types' -import type { ID, SegmentEvent, User } from '@segment/analytics-next' -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -type CachedUser = { - id: ID - anonymousId: ID - traits: ReturnType | null -} - -let cachedUser: CachedUser = { - id: undefined, - anonymousId: undefined, - traits: null -} - -export function resetUserCache() { - cachedUser = { - id: undefined, - anonymousId: undefined, - traits: null - } -} - -function shouldSendToBraze(event: SegmentEvent) { - if (event.userId && event.userId !== cachedUser.id) { - return true - } - - if (event.anonymousId && event.anonymousId !== cachedUser.anonymousId) { - return true - } - - const traits = event.traits ?? {} - return JSON.stringify(cachedUser.traits) !== JSON.stringify(traits) -} - -const action: BrowserActionDefinition = { - title: 'Debounce Middleware', - description: - 'When enabled, it ensures that only events where at least one changed trait value are sent to Braze, and events with duplicate traits are not sent. Debounce functionality requires a frontend client to work. Therefore, it cannot be used with server-side libraries or with Engage.', - platform: 'web', - defaultSubscription: 'type = "identify" or type = "group"', - fields: {}, - lifecycleHook: 'before', - perform: (_client, data) => { - const event = data.context.event - const analyticsUser = data.analytics.user() - const ctx = data.context - - // Only send the event to Braze if a trait has changed - // Target all possible Braze integration names - const shouldSend = shouldSendToBraze(event) - ctx.updateEvent('integrations.Braze Web Mode (Actions)', shouldSend) - ctx.updateEvent('integrations.Braze Cloud Mode (Actions)', shouldSend) - ctx.updateEvent('integrations.Appboy', shouldSend) - - // Ensure analytics.user is defined - cachedUser.id = analyticsUser.id() - cachedUser.anonymousId = analyticsUser.anonymousId() - cachedUser.traits = analyticsUser.traits() - } -} - -export default action diff --git a/packages/browser-destinations/destinations/braze/src/generated-types.ts b/packages/browser-destinations/destinations/braze/src/generated-types.ts deleted file mode 100644 index 1886e11a53..0000000000 --- a/packages/browser-destinations/destinations/braze/src/generated-types.ts +++ /dev/null @@ -1,104 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * The version of the Braze SDK to use - */ - sdkVersion: string - /** - * Found in the Braze Dashboard under Manage Settings → Apps → Web - */ - api_key: string - /** - * Your Braze SDK endpoint. [See more details](https://www.braze.com/docs/user_guide/administrative/access_braze/sdk_endpoints/) - */ - endpoint: string - /** - * Allow Braze to log activity from crawlers. [See more details](https://js.appboycdn.com/web-sdk/latest/doc/modules/appboy.html#initializationoptions) - */ - allowCrawlerActivity?: boolean - /** - * To indicate that you trust the Braze dashboard users to write non-malicious Javascript click actions, set this property to true. If enableHtmlInAppMessages is true, this option will also be set to true. [See more details](https://js.appboycdn.com/web-sdk/latest/doc/modules/appboy.html#initializationoptions) - */ - allowUserSuppliedJavascript?: boolean - /** - * If enabled, this setting delays initialization of the Braze SDK until the user has been identified. When enabled, events for anonymous users will no longer be sent to Braze. - */ - deferUntilIdentified?: boolean - /** - * Version to which user events sent to Braze will be associated with. [See more details](https://js.appboycdn.com/web-sdk/latest/doc/modules/appboy.html#initializationoptions) - */ - appVersion?: string - /** - * Allows Braze to add the nonce to any , - ] - `) - - expect(window.bucket).toMatchObject({ - init: expect.any(Function), - user: expect.any(Function), - company: expect.any(Function), - track: expect.any(Function), - reset: expect.any(Function) - }) - }) - - it('resets the Bucket SDK', async () => { - const [instance] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) - - await instance.load(Context.system(), analyticsInstance) - - analyticsInstance.reset() - - expect(getBucketCallLog()).toStrictEqual([ - { method: 'init', args: ['testTrackingKey', {}] }, - { method: 'reset', args: [] } - ]) - }) - - it('passes options to bucket.init()', async () => { - const [instance] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - host: 'http://localhost:3200', - subscriptions: subscriptions as unknown as JSONArray - }) - - const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) - - await instance.load(Context.system(), analyticsInstance) - - expect(getBucketCallLog()).toStrictEqual([ - { method: 'init', args: ['testTrackingKey', { host: 'http://localhost:3200' }] } - ]) - }) - - it('allows sdkVersion override', async () => { - const [instance] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - sdkVersion: 'latest', - subscriptions: subscriptions as unknown as JSONArray - }) - - const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) - - await instance.load(Context.system(), analyticsInstance) - - const scripts = Array.from(window.document.querySelectorAll('script')) - expect(scripts).toMatchInlineSnapshot(` - Array [ - , - ] - `) - - expect(getBucketCallLog()).toStrictEqual([{ method: 'init', args: ['testTrackingKey', {}] }]) - }) - - describe('when not logged in', () => { - it('initializes Bucket SDK', async () => { - const [instance] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) - - await instance.load(Context.system(), analyticsInstance) - - expect(getBucketCallLog()).toStrictEqual([{ method: 'init', args: ['testTrackingKey', {}] }]) - }) - }) - - describe('when logged in', () => { - it('initializes Bucket SDK and registers user', async () => { - const [instance] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) - jest.spyOn(analyticsInstance, 'user').mockImplementation( - () => - ({ - id: () => 'test-user-id-1' - } as User) - ) - - await instance.load(Context.system(), analyticsInstance) - - expect(getBucketCallLog()).toStrictEqual([ - { method: 'init', args: ['testTrackingKey', {}] }, - { method: 'user', args: ['test-user-id-1', {}, { active: false }] } - ]) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/bucket/src/generated-types.ts b/packages/browser-destinations/destinations/bucket/src/generated-types.ts deleted file mode 100644 index 87197ad986..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * The publishable key for your Bucket environment, found on the tracking page on app.bucket.co. - */ - trackingKey: string -} diff --git a/packages/browser-destinations/destinations/bucket/src/group/__tests__/index.test.ts b/packages/browser-destinations/destinations/bucket/src/group/__tests__/index.test.ts deleted file mode 100644 index fbba8d8467..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/group/__tests__/index.test.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { Analytics, Context, User } from '@segment/analytics-next' -import bucketWebDestination, { destination } from '../../index' -import { Subscription } from '@segment/browser-destination-runtime/types' -import { JSONArray } from '@segment/actions-core/*' -import { bucketTestHooks, getBucketCallLog } from '../../test-utils' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'group', - name: 'Identify Company', - enabled: true, - subscribe: 'type = "group"', - mapping: { - groupId: { - '@path': '$.groupId' - }, - userId: { - '@path': '$.userId' - }, - traits: { - '@path': '$.traits' - } - } - } -] - -describe('Bucket.company', () => { - bucketTestHooks() - - describe('when logged in', () => { - describe('from analytics.js previous session', () => { - it('maps parameters correctly to Bucket', async () => { - const [bucketPlugin] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) - jest.spyOn(analyticsInstance, 'user').mockImplementation( - () => - ({ - id: () => 'user-id-1' - } as User) - ) - await bucketPlugin.load(Context.system(), analyticsInstance) - - jest.spyOn(destination.actions.group, 'perform') - - await bucketPlugin.group?.( - new Context({ - type: 'group', - userId: 'user-id-1', - groupId: 'group-id-1', - traits: { - name: 'ACME INC' - } - }) - ) - - expect(destination.actions.group.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - userId: 'user-id-1', - groupId: 'group-id-1', - traits: { - name: 'ACME INC' - } - } - }) - ) - - expect(getBucketCallLog()).toStrictEqual([ - { method: 'init', args: ['testTrackingKey', {}] }, - { - method: 'user', - args: ['user-id-1', {}, { active: false }] - }, - { - method: 'company', - args: [ - 'group-id-1', - { - name: 'ACME INC' - }, - 'user-id-1' - ] - } - ]) - }) - }) - - describe('from am identify call', () => { - it('maps parameters correctly to Bucket', async () => { - const [bucketPlugin] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - await bucketPlugin.load(Context.system(), new Analytics({ writeKey: 'test-writekey' })) - - jest.spyOn(destination.actions.group, 'perform') - - // Bucket rejects group calls without previous identify calls - await window.bucket.user('user-id-1') - - await bucketPlugin.group?.( - new Context({ - type: 'group', - userId: 'user-id-1', - groupId: 'group-id-1', - traits: { - name: 'ACME INC' - } - }) - ) - - expect(destination.actions.group.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - userId: 'user-id-1', - groupId: 'group-id-1', - traits: { - name: 'ACME INC' - } - } - }) - ) - - expect(getBucketCallLog()).toStrictEqual([ - { method: 'init', args: ['testTrackingKey', {}] }, - { - method: 'user', - args: ['user-id-1'] - }, - { - method: 'company', - args: [ - 'group-id-1', - { - name: 'ACME INC' - }, - 'user-id-1' - ] - } - ]) - }) - }) - }) - - describe('when not logged in', () => { - it('should not call Bucket.group', async () => { - const [bucketPlugin] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) - await bucketPlugin.load(Context.system(), analyticsInstance) - - jest.spyOn(destination.actions.group, 'perform') - - // Manually mimicking a group call without a userId. - // The analytics client will probably never do this if - // userId doesn't exist, since the subscription marks it as required - await bucketPlugin.group?.( - new Context({ - type: 'group', - anonymousId: 'anonymous-id-1', - groupId: 'group-id-1', - traits: { - name: 'ACME INC' - } - }) - ) - - // TODO: Ideally we should be able to assert that the destination action was never - // called, but couldn't figure out how to create an anlytics instance with the plugin - // and then trigger the full flow trhough analytics.group() with only an anonymous ID - // expect(destination.actions.group.perform).not.toHaveBeenCalled() - - expect(getBucketCallLog()).toStrictEqual([{ method: 'init', args: ['testTrackingKey', {}] }]) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/bucket/src/group/generated-types.ts b/packages/browser-destinations/destinations/bucket/src/group/generated-types.ts deleted file mode 100644 index ff9f16892c..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/group/generated-types.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * Unique identifier for the company - */ - groupId: string - /** - * Unique identifier for the user - */ - userId: string - /** - * Additional information to associate with the Company in Bucket - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/bucket/src/group/index.ts b/packages/browser-destinations/destinations/bucket/src/group/index.ts deleted file mode 100644 index a4162da1e1..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/group/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { Bucket } from '../types' - -const action: BrowserActionDefinition = { - title: 'Identify Company', - description: 'Creates or updates a Company in Bucket and associates the user with it', - platform: 'web', - defaultSubscription: 'type = "group"', - fields: { - groupId: { - type: 'string', - required: true, - description: 'Unique identifier for the company', - label: 'Company ID', - default: { - '@path': '$.groupId' - } - }, - userId: { - type: 'string', - required: true, - allowNull: false, - description: 'Unique identifier for the user', - label: 'User ID', - default: { - '@path': '$.userId' - } - }, - traits: { - type: 'object', - required: false, - description: 'Additional information to associate with the Company in Bucket', - label: 'Company Attributes', - default: { - '@path': '$.traits' - } - } - }, - perform: (bucket, { payload }) => { - // Ensure we never call Bucket.company() without a user ID - if (payload.userId) { - void bucket.company(payload.groupId, payload.traits, payload.userId) - } - } -} - -export default action diff --git a/packages/browser-destinations/destinations/bucket/src/identifyUser/__tests__/index.test.ts b/packages/browser-destinations/destinations/bucket/src/identifyUser/__tests__/index.test.ts deleted file mode 100644 index 51a7e58239..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/identifyUser/__tests__/index.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import bucketWebDestination, { destination } from '../../index' -import { Subscription } from '@segment/browser-destination-runtime/types' -import { JSONArray } from '@segment/actions-core/*' -import { bucketTestHooks, getBucketCallLog } from '../../test-utils' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'identifyUser', - name: 'Identify User', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - userId: { - '@path': '$.userId' - }, - traits: { - '@path': '$.traits' - } - } - } -] - -describe('Bucket.user', () => { - bucketTestHooks() - - test('it maps event parameters correctly to bucket.user', async () => { - const [identifyEvent] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - await identifyEvent.load(Context.system(), new Analytics({ writeKey: 'test-writekey' })) - - jest.spyOn(destination.actions.identifyUser, 'perform') - - await identifyEvent.identify?.( - new Context({ - type: 'identify', - userId: 'user-id-1', - traits: { - name: 'John Doe', - email: 'test-email-2@gmail.com', - age: 42 - } - }) - ) - - expect(destination.actions.identifyUser.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - userId: 'user-id-1', - traits: { - name: 'John Doe', - email: 'test-email-2@gmail.com', - age: 42 - } - } - }) - ) - - expect(getBucketCallLog()).toStrictEqual([ - { method: 'init', args: ['testTrackingKey', {}] }, - { - method: 'user', - args: [ - 'user-id-1', - { - name: 'John Doe', - email: 'test-email-2@gmail.com', - age: 42 - } - ] - } - ]) - }) -}) diff --git a/packages/browser-destinations/destinations/bucket/src/identifyUser/generated-types.ts b/packages/browser-destinations/destinations/bucket/src/identifyUser/generated-types.ts deleted file mode 100644 index 2703e2cb3c..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/identifyUser/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * Unique identifier for the User - */ - userId: string - /** - * Additional information to associate with the User in Bucket - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/bucket/src/identifyUser/index.ts b/packages/browser-destinations/destinations/bucket/src/identifyUser/index.ts deleted file mode 100644 index 4472b52cc9..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/identifyUser/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { Bucket } from '../types' - -const action: BrowserActionDefinition = { - title: 'Identify User', - description: 'Creates or updates a user profile in Bucket. Also initializes Live Satisfaction', - platform: 'web', - defaultSubscription: 'type = "identify"', - fields: { - userId: { - type: 'string', - required: true, - description: 'Unique identifier for the User', - label: 'User ID', - default: { - '@path': '$.userId' - } - }, - traits: { - type: 'object', - required: false, - description: 'Additional information to associate with the User in Bucket', - label: 'User Attributes', - default: { - '@path': '$.traits' - } - } - }, - perform: (bucket, { payload }) => { - void bucket.user(payload.userId, payload.traits) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/bucket/src/index.ts b/packages/browser-destinations/destinations/bucket/src/index.ts deleted file mode 100644 index 87305ba434..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/index.ts +++ /dev/null @@ -1,97 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import { Bucket } from './types' -import identifyUser from './identifyUser' -import trackEvent from './trackEvent' -import { defaultValues } from '@segment/actions-core' -import group from './group' - -declare global { - interface Window { - bucket: Bucket - } -} - -export const destination: BrowserDestinationDefinition = { - name: 'Bucket Web (Actions)', - description: - 'Loads the Bucket browser SDK, maps identify(), group() and track() events and enables LiveSatisfaction connections', - slug: 'bucket-web', - mode: 'device', - - presets: [ - { - name: 'Identify User', - subscribe: 'type = "identify"', - partnerAction: 'identifyUser', - mapping: defaultValues(identifyUser.fields), - type: 'automatic' - }, - { - name: 'Group', - subscribe: 'type = "group"', - partnerAction: 'group', - mapping: defaultValues(group.fields), - type: 'automatic' - }, - { - name: 'Track Event', - subscribe: 'type = "track"', - partnerAction: 'trackEvent', - mapping: defaultValues(trackEvent.fields), - type: 'automatic' - } - ], - - settings: { - // kept as the legacy `trackingKey` here to avoid needing to migrate installed plugins - trackingKey: { - description: 'The publishable key for your Bucket environment, found on the tracking page on app.bucket.co.', - label: 'Publishable Key', - type: 'string', - required: true - } - }, - - actions: { - identifyUser, - group, - trackEvent - }, - - initialize: async ({ settings, analytics }, deps) => { - const { - // @ts-expect-error versionSettings is not part of the settings object but they are injected by Analytics 2.0, making Braze SDK raise a warning when we initialize it. - versionSettings, - // @ts-expect-error same as above. - subscriptions, - - trackingKey, - // @ts-expect-error Code-only SDK version override. Can be set via analytics.load() integrations overrides - sdkVersion = '2', - ...options - } = settings - await deps.loadScript(`https://cdn.jsdelivr.net/npm/@bucketco/tracking-sdk@${sdkVersion}`) - await deps.resolveWhen(() => window.bucket != undefined, 100) - - window.bucket.init(settings.trackingKey, options) - - // If the analytics client already has a logged in user from a - // previous session or page, consider the user logged in. - // In this case we need to call `bucket.user()` to set the persisted - // user id in bucket and initialize Live Satisfaction - const segmentPersistedUserId = analytics.user().id() - if (segmentPersistedUserId) { - void window.bucket.user(segmentPersistedUserId, {}, { active: false }) - } - - analytics.on('reset', () => { - window.bucket.reset() - }) - - return window.bucket - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/bucket/src/test-utils.ts b/packages/browser-destinations/destinations/bucket/src/test-utils.ts deleted file mode 100644 index baabbb6e6d..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/test-utils.ts +++ /dev/null @@ -1,63 +0,0 @@ -import nock from 'nock' -import { Bucket } from 'src/types' - -const bucketTestMock = ` -(() => { - const noop = () => {}; - - const bucketTestInterface = { - init: noop, - user: noop, - company: noop, - track: noop, - reset: noop - }; - - const callLog = []; - - window.bucket = new Proxy(bucketTestInterface, { - get(bucket, property) { - if (typeof bucket[property] === 'function') { - return (...args) => { - callLog.push({ method: property, args }) - return bucket[property](...args) - } - } - - if (property === 'callLog') { - return callLog; - } - } - }); -})(); -` - -export function bucketTestHooks() { - beforeAll(() => { - nock.disableNetConnect() - }) - - beforeEach(() => { - nock('https://cdn.jsdelivr.net') - .get((uri) => uri.startsWith('/npm/@bucketco/tracking-sdk@')) - .reply(200, bucketTestMock) - }) - - afterEach(function () { - if (!nock.isDone()) { - // @ts-expect-error no-unsafe-call - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - this.test.error(new Error('Not all nock interceptors were used!')) - } - - nock.cleanAll() - }) - - afterAll(() => { - nock.enableNetConnect() - }) -} - -export function getBucketCallLog() { - return (window.bucket as unknown as { callLog: Array<{ method: keyof Bucket; args: Array }> }).callLog -} diff --git a/packages/browser-destinations/destinations/bucket/src/trackEvent/__tests__/index.test.ts b/packages/browser-destinations/destinations/bucket/src/trackEvent/__tests__/index.test.ts deleted file mode 100644 index 5c94ef5aab..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/trackEvent/__tests__/index.test.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { Analytics, Context, User } from '@segment/analytics-next' -import bucketWebDestination, { destination } from '../../index' -import { Subscription } from '@segment/browser-destination-runtime/types' -import { JSONArray } from '@segment/actions-core/*' -import { bucketTestHooks, getBucketCallLog } from '../../test-utils' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'trackEvent', - name: 'Track Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - name: { - '@path': '$.name' - }, - userId: { - '@path': '$.userId' - }, - properties: { - '@path': '$.properties' - } - } - } -] - -describe('trackEvent', () => { - bucketTestHooks() - - describe('when logged in', () => { - describe('from analytics.js previous session', () => { - it('maps parameters correctly to Bucket', async () => { - const [bucketPlugin] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) - jest.spyOn(analyticsInstance, 'user').mockImplementation( - () => - ({ - id: () => 'user-id-1' - } as User) - ) - await bucketPlugin.load(Context.system(), analyticsInstance) - - jest.spyOn(destination.actions.trackEvent, 'perform') - - const properties = { property1: 'value1', property2: false } - await bucketPlugin.track?.( - new Context({ - type: 'track', - name: 'Button Clicked', - userId: 'user-id-1', - properties - }) - ) - - expect(destination.actions.trackEvent.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { name: 'Button Clicked', userId: 'user-id-1', properties } - }) - ) - - expect(getBucketCallLog()).toStrictEqual([ - { method: 'init', args: ['testTrackingKey', {}] }, - { - method: 'user', - args: ['user-id-1', {}, { active: false }] - }, - { - method: 'track', - args: ['Button Clicked', properties, 'user-id-1'] - } - ]) - }) - }) - - describe('from am identify call', () => { - it('maps parameters correctly to Bucket', async () => { - const [bucketPlugin] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - await bucketPlugin.load(Context.system(), new Analytics({ writeKey: 'test-writekey' })) - - jest.spyOn(destination.actions.trackEvent, 'perform') - - // Bucket rejects group calls without previous identify calls - await window.bucket.user('user-id-1') - - const properties = { property1: 'value1', property2: false } - await bucketPlugin.track?.( - new Context({ - type: 'track', - name: 'Button Clicked', - userId: 'user-id-1', - properties - }) - ) - - expect(destination.actions.trackEvent.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { name: 'Button Clicked', userId: 'user-id-1', properties } - }) - ) - - expect(getBucketCallLog()).toStrictEqual([ - { method: 'init', args: ['testTrackingKey', {}] }, - { - method: 'user', - args: ['user-id-1'] - }, - { - method: 'track', - args: ['Button Clicked', properties, 'user-id-1'] - } - ]) - }) - }) - }) - - describe('when not logged in', () => { - it('should not call Bucket.group', async () => { - const [bucketPlugin] = await bucketWebDestination({ - trackingKey: 'testTrackingKey', - subscriptions: subscriptions as unknown as JSONArray - }) - - const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) - await bucketPlugin.load(Context.system(), analyticsInstance) - - jest.spyOn(destination.actions.trackEvent, 'perform') - - // Manually mimicking a track call without a userId. - // The analytics client will probably never do this if - // userId doesn't exist, since the subscription marks it as required - const properties = { property1: 'value1', property2: false } - await bucketPlugin.track?.( - new Context({ - type: 'track', - name: 'Button Clicked', - anonymousId: 'user-id-1', - properties - }) - ) - - // TODO: Ideally we should be able to assert that the destination action was never - // called, but couldn't figure out how to create an anlytics instance with the plugin - // and then trigger the full flow trhough analytics.track() with only an anonymous ID - // expect(destination.actions.trackEvent.perform).not.toHaveBeenCalled() - - expect(getBucketCallLog()).toStrictEqual([{ method: 'init', args: ['testTrackingKey', {}] }]) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/bucket/src/trackEvent/generated-types.ts b/packages/browser-destinations/destinations/bucket/src/trackEvent/generated-types.ts deleted file mode 100644 index 2d7e5e4aed..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/trackEvent/generated-types.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The event name - */ - name: string - /** - * Unique identifier for the user - */ - userId: string - /** - * Object containing the properties of the event - */ - properties?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/bucket/src/trackEvent/index.ts b/packages/browser-destinations/destinations/bucket/src/trackEvent/index.ts deleted file mode 100644 index 29bf9a30fb..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/trackEvent/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { Bucket } from '../types' - -const action: BrowserActionDefinition = { - title: 'Track Event', - description: 'Map a Segment track() event to Bucket', - platform: 'web', - defaultSubscription: 'type = "track"', - fields: { - name: { - description: 'The event name', - label: 'Event name', - required: true, - type: 'string', - default: { - '@path': '$.event' - } - }, - userId: { - type: 'string', - required: true, - allowNull: false, - description: 'Unique identifier for the user', - label: 'User ID', - default: { - '@path': '$.userId' - } - }, - properties: { - type: 'object', - required: false, - description: 'Object containing the properties of the event', - label: 'Event Properties', - default: { - '@path': '$.properties' - } - } - }, - perform: (bucket, { payload }) => { - // Ensure we never call Bucket.track() without a user ID - if (payload.userId) { - void bucket.track(payload.name, payload.properties, payload.userId) - } - } -} - -export default action diff --git a/packages/browser-destinations/destinations/bucket/src/types.ts b/packages/browser-destinations/destinations/bucket/src/types.ts deleted file mode 100644 index 4307622bca..0000000000 --- a/packages/browser-destinations/destinations/bucket/src/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type bucket from '@bucketco/tracking-sdk' - -export type Bucket = typeof bucket diff --git a/packages/browser-destinations/destinations/bucket/tsconfig.json b/packages/browser-destinations/destinations/bucket/tsconfig.json deleted file mode 100644 index c2a7897afd..0000000000 --- a/packages/browser-destinations/destinations/bucket/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} diff --git a/packages/browser-destinations/destinations/cdpresolution/README.md b/packages/browser-destinations/destinations/cdpresolution/README.md deleted file mode 100644 index 7450e7d182..0000000000 --- a/packages/browser-destinations/destinations/cdpresolution/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# @segment/analytics-browser-actions-cdpresolution - -The Cdpresolution browser action destination for use with @segment/analytics-next. - -## License - -MIT License - -Copyright (c) 2024 Segment - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -## Contributing - -All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. diff --git a/packages/browser-destinations/destinations/cdpresolution/package.json b/packages/browser-destinations/destinations/cdpresolution/package.json deleted file mode 100644 index 3fe9e0af9a..0000000000 --- a/packages/browser-destinations/destinations/cdpresolution/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-cdpresolution", - "version": "1.34.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/cdpresolution/src/generated-types.ts b/packages/browser-destinations/destinations/cdpresolution/src/generated-types.ts deleted file mode 100644 index 8259b5093c..0000000000 --- a/packages/browser-destinations/destinations/cdpresolution/src/generated-types.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * Client identifier provided by CDP Resolution [Hashed Account ID] - */ - clientIdentifier: string - /** - * Identity resolution endpoint. [CDP Resolution documentation](https://www.cdpresolution.com/docs/) - */ - endpoint: string -} diff --git a/packages/browser-destinations/destinations/cdpresolution/src/index.ts b/packages/browser-destinations/destinations/cdpresolution/src/index.ts deleted file mode 100644 index c5cf2356f4..0000000000 --- a/packages/browser-destinations/destinations/cdpresolution/src/index.ts +++ /dev/null @@ -1,100 +0,0 @@ -// Module: Initialize code -// Version: 1.0 -// Changes: -// - Initial Version (A.Sikri) -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import { DestinationDefinition, defaultValues } from '@segment/actions-core' -import { CDPResolution } from './types' -import sync from './sync' - -declare global { - interface Window { - cdpResolution: CDPResolution - } -} - -const presets: DestinationDefinition['presets'] = [ - { - name: 'Sync Anonymous ID', - subscribe: 'type = "page" or type = "track" or type = "identify"', - partnerAction: 'sync', - mapping: defaultValues(sync.fields), - type: 'automatic' - } -] - -// Switch from unknown to the partner SDK client types -export const destination: BrowserDestinationDefinition = { - name: 'CDP Resolution', - slug: 'actions-cdpresolution', - mode: 'device', - description: 'Sync Segment user identifier to CDP Resolution', - settings: { - // Add any Segment destination settings required here - clientIdentifier: { - label: 'Client Identifier', - description: 'Client identifier provided by CDP Resolution [Hashed Account ID]', - type: 'string', - required: true - }, - endpoint: { - label: 'CDP Resolution Endpoint', - description: 'Identity resolution endpoint. [CDP Resolution documentation](https://www.cdpresolution.com/docs/)', - type: 'string', - format: 'uri', - choices: [{ label: 'CDPRes-Endpoint', value: 'https://a.usbrowserspeed.com/cs' }], - default: 'https://a.usbrowserspeed.com/cs', - required: true - } - }, - - initialize: async (_, deps) => { - window.cdpResolution = { - sync: async (endpoint: string, clientIdentifier: string, anonymousId: string): Promise => { - let cdpcookieset = '' - const name = 'cdpresolutionset' + '=' - const ca = document.cookie.split(';') - for (let i = 0; i < ca.length; i++) { - let c = ca[i] - while (c.charAt(0) == ' ') { - c = c.substring(1) - } - if (c.indexOf(name) == 0) { - cdpcookieset = c.substring(name.length, c.length) - } - } - - const pid = '48a021d87720f17403d730658979d7f60e9cec91937e82072c66f611748dd47d' - const userAnonymousId: string | null = String(anonymousId) - const baseUrl = endpoint - - const partnerUserId = { - client_id: clientIdentifier, - visitor_id: userAnonymousId - } - const partnerUserIdStr = encodeURIComponent(JSON.stringify(partnerUserId)) - - const endpointUrl = userAnonymousId - ? `${baseUrl}?pid=${pid}&puid=${partnerUserIdStr}&anonymousId=${encodeURIComponent(userAnonymousId)}` - : baseUrl - - if (cdpcookieset == '') { - document.cookie = 'cdpresolutionset=true' - await deps.loadScript(endpointUrl) - return - } - } - } - - return window.cdpResolution - }, - - presets, - actions: { - sync - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/cdpresolution/src/sync/__tests__/index.test.ts b/packages/browser-destinations/destinations/cdpresolution/src/sync/__tests__/index.test.ts deleted file mode 100644 index e554f90c67..0000000000 --- a/packages/browser-destinations/destinations/cdpresolution/src/sync/__tests__/index.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime' -import cdpResolutionDestination, { destination } from '../../index' -import { CDPResolution } from '../../types' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'sync', - name: 'Sync Anonymous ID', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - anonymousId: { - '@path': '$.anonymousId' - } - } - } -] - -describe('CDPResolution.sync', () => { - const settings = { - endpoint: 'https://a.usbrowserspeed.com/cs', - clientIdentifier: 'clientid1' - } - - let mockCDPResolution: CDPResolution - let syncAction: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [syncEvent] = await cdpResolutionDestination({ - ...settings, - subscriptions - }) - syncAction = syncEvent - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockCDPResolution = { - sync: jest.fn() - } - return Promise.resolve(mockCDPResolution) - }) - await syncAction.load(Context.system(), {} as Analytics) - }) - - test('calls the cdpResolution Client sync() function', async () => { - const context = new Context({ - type: 'identify', - anonymousId: 'aid1' - }) - await syncAction.identify?.(context) - - expect(mockCDPResolution.sync).toHaveBeenCalledWith('https://a.usbrowserspeed.com/cs', 'clientid1', 'aid1') - }) -}) diff --git a/packages/browser-destinations/destinations/cdpresolution/src/sync/generated-types.ts b/packages/browser-destinations/destinations/cdpresolution/src/sync/generated-types.ts deleted file mode 100644 index a8bb85193e..0000000000 --- a/packages/browser-destinations/destinations/cdpresolution/src/sync/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The anonymous id of the user - */ - anonymousId: string -} diff --git a/packages/browser-destinations/destinations/cdpresolution/src/sync/index.ts b/packages/browser-destinations/destinations/cdpresolution/src/sync/index.ts deleted file mode 100644 index e715308737..0000000000 --- a/packages/browser-destinations/destinations/cdpresolution/src/sync/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Module: Sync event code -// Version: 1.0 -// Changes: -// - Initial Version (A.Sikri) -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { CDPResolution } from '../types' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Sync Anonymous ID', - description: 'Sync Anonymous ID to CDP Resolution.', - defaultSubscription: 'type = "page" or type = "track" or type = "identify"', - platform: 'web', - fields: { - anonymousId: { - label: 'Anonymous Id', - description: 'The anonymous id of the user', - type: 'string', - required: true, - default: { - '@path': '$.anonymousId' - } - } - }, - perform: (cdpResolution, { settings, payload }) => { - cdpResolution.sync(settings.endpoint, settings.clientIdentifier, payload.anonymousId) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/cdpresolution/src/types.ts b/packages/browser-destinations/destinations/cdpresolution/src/types.ts deleted file mode 100644 index 89a5276960..0000000000 --- a/packages/browser-destinations/destinations/cdpresolution/src/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type CDPResolution = { - sync: (endpoint: string, ClientIdentifier: string, anonymousId: string) => void -} diff --git a/packages/browser-destinations/destinations/cdpresolution/tsconfig.json b/packages/browser-destinations/destinations/cdpresolution/tsconfig.json deleted file mode 100644 index c2a7897afd..0000000000 --- a/packages/browser-destinations/destinations/cdpresolution/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} diff --git a/packages/browser-destinations/destinations/commandbar/package.json b/packages/browser-destinations/destinations/commandbar/package.json deleted file mode 100644 index 2f9de5f3bb..0000000000 --- a/packages/browser-destinations/destinations/commandbar/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-commandbar", - "version": "1.47.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/actions-core": "^3.116.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/commandbar/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/commandbar/src/__tests__/index.test.ts deleted file mode 100644 index b631e25601..0000000000 --- a/packages/browser-destinations/destinations/commandbar/src/__tests__/index.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import commandBarDestination, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'trackEvent', - name: 'Show', - enabled: true, - subscribe: 'type = "track"', - mapping: { - event_name: { - '@path': '$.event' - }, - event_metadata: { - '@path': '$.properties' - } - } - } -] - -describe('CommandBar initialization', () => { - test('can load CommandBar with just orgId', async () => { - const [event] = await commandBarDestination({ - orgId: '05f077f2', - subscriptions - }) - jest.spyOn(destination, 'initialize') - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - const scripts = window.document.querySelectorAll('script') - expect(scripts).toMatchInlineSnapshot(` - NodeList [ - , - , - ] - `) -}) diff --git a/packages/browser-destinations/destinations/fullstory/src/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/generated-types.ts deleted file mode 100644 index 66c24932c0..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/generated-types.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * The organization ID for FullStory. - */ - orgId: string - /** - * Enables FullStory debug mode. - */ - debug?: boolean - /** - * Enables FullStory inside an iframe. - */ - recordOnlyThisIFrame?: boolean -} diff --git a/packages/browser-destinations/destinations/fullstory/src/identifyUser/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/identifyUser/generated-types.ts deleted file mode 100644 index e325fbc445..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/identifyUser/generated-types.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The user's id - */ - userId?: string - /** - * The user's anonymous id - */ - anonymousId?: string - /** - * The user's display name - */ - displayName?: string - /** - * The user's email - */ - email?: string - /** - * The Segment traits to be forwarded to FullStory - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/fullstory/src/identifyUser/index.ts b/packages/browser-destinations/destinations/fullstory/src/identifyUser/index.ts deleted file mode 100644 index 591edc9154..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/identifyUser/index.ts +++ /dev/null @@ -1,125 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { FS } from '../types' -import camelCase from 'lodash/camelCase' -import { segmentEventSource } from '..' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Identify User', - description: 'Sets user identity variables', - platform: 'web', - defaultSubscription: 'type = "identify"', - fields: { - userId: { - type: 'string', - required: false, - description: "The user's id", - label: 'User ID', - default: { - '@path': '$.userId' - } - }, - anonymousId: { - type: 'string', - required: false, - description: "The user's anonymous id", - label: 'Anonymous ID', - default: { - '@path': '$.anonymousId' - } - }, - displayName: { - type: 'string', - required: false, - description: "The user's display name", - label: 'Display Name', - default: { - '@path': '$.traits.name' - } - }, - email: { - type: 'string', - required: false, - description: "The user's email", - label: 'Email', - default: { - '@path': '$.traits.email' - } - }, - traits: { - type: 'object', - required: false, - description: 'The Segment traits to be forwarded to FullStory', - label: 'Traits', - default: { - '@path': '$.traits' - } - } - }, - perform: (FS, event) => { - let newTraits: Record = {} - - if (event.payload.traits) { - newTraits = Object.entries(event.payload.traits).reduce( - (acc, [key, value]) => ({ - ...acc, - [camelCaseField(key)]: value - }), - {} - ) - } - - if (event.payload.anonymousId) { - newTraits.segmentAnonymousId_str = event.payload.anonymousId - } - - const userVars = { - ...newTraits, - ...(event.payload.email !== undefined && { email: event.payload.email }), - ...(event.payload.displayName !== undefined && { displayName: event.payload.displayName }) - } - - if (event.payload.userId) { - FS.identify(event.payload.userId, userVars, segmentEventSource) - } else { - FS.setUserVars(userVars, segmentEventSource) - } - } -} - -/** - * Camel cases `.`, `-`, `_`, and white space within fieldNames. Leaves type suffix alone. - * - * NOTE: Does not fix otherwise malformed fieldNames. - * FullStory will scrub characters from keys that do not conform to /^[a-zA-Z][a-zA-Z0-9_]*$/. - * - * @param {string} fieldName - */ -function camelCaseField(fieldName: string) { - // Do not camel case across type suffixes. - const parts = fieldName.split('_') - if (parts.length > 1) { - const typeSuffix = parts.pop() - switch (typeSuffix) { - case 'str': - case 'int': - case 'date': - case 'real': - case 'bool': - case 'strs': - case 'ints': - case 'dates': - case 'reals': - case 'bools': - return camelCase(parts.join('_')) + '_' + typeSuffix - default: // passthrough - } - } - - // No type suffix found. Camel case the whole field name. - return camelCase(fieldName) -} - -export default action diff --git a/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/generated-types.ts deleted file mode 100644 index e325fbc445..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/generated-types.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The user's id - */ - userId?: string - /** - * The user's anonymous id - */ - anonymousId?: string - /** - * The user's display name - */ - displayName?: string - /** - * The user's email - */ - email?: string - /** - * The Segment traits to be forwarded to FullStory - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/index.ts b/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/index.ts deleted file mode 100644 index 97e7db1e7f..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/index.ts +++ /dev/null @@ -1,95 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { FS } from '../types' -import { segmentEventSource } from '..' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Identify User V2', - description: 'Sets user identity properties', - platform: 'web', - defaultSubscription: 'type = "identify"', - fields: { - userId: { - type: 'string', - required: false, - description: "The user's id", - label: 'User ID', - default: { - '@path': '$.userId' - } - }, - anonymousId: { - type: 'string', - required: false, - description: "The user's anonymous id", - label: 'Anonymous ID', - default: { - '@path': '$.anonymousId' - } - }, - displayName: { - type: 'string', - required: false, - description: "The user's display name", - label: 'Display Name', - default: { - '@path': '$.traits.name' - } - }, - email: { - type: 'string', - required: false, - description: "The user's email", - label: 'Email', - default: { - '@path': '$.traits.email' - } - }, - traits: { - type: 'object', - required: false, - description: 'The Segment traits to be forwarded to FullStory', - label: 'Traits', - default: { - '@path': '$.traits' - } - } - }, - perform: (FS, event) => { - const newTraits: Record = event.payload.traits || {} - - if (event.payload.anonymousId) { - newTraits.segmentAnonymousId = event.payload.anonymousId - } - - const userProperties = { - ...newTraits, - ...(event.payload.email !== undefined && { email: event.payload.email }), - ...(event.payload.displayName !== undefined && { displayName: event.payload.displayName }) - } - - if (event.payload.userId) { - FS( - 'setIdentity', - { - uid: event.payload.userId, - properties: userProperties - }, - segmentEventSource - ) - } else { - FS( - 'setProperties', - { - type: 'user', - properties: userProperties - }, - segmentEventSource - ) - } - } -} - -export default action diff --git a/packages/browser-destinations/destinations/fullstory/src/index.ts b/packages/browser-destinations/destinations/fullstory/src/index.ts deleted file mode 100644 index 01b1ac4d75..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -import type { FS } from './types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { initFullStory } from './types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import type { Settings } from './generated-types' -import trackEvent from './trackEvent' -import trackEventV2 from './trackEventV2' -import identifyUser from './identifyUser' -import identifyUserV2 from './identifyUserV2' -import viewedPage from './viewedPage' -import viewedPageV2 from './viewedPageV2' -import { defaultValues } from '@segment/actions-core' - -declare global { - interface Window { - FS: FS - } -} - -export const segmentEventSource = 'segment-browser-actions' - -export const destination: BrowserDestinationDefinition = { - name: 'Fullstory (Actions)', - slug: 'actions-fullstory', - mode: 'device', - presets: [ - { - name: 'Track Event', - subscribe: 'type = "track"', - partnerAction: 'trackEventV2', - mapping: defaultValues(trackEventV2.fields), - type: 'automatic' - }, - { - name: 'Identify User', - subscribe: 'type = "identify"', - partnerAction: 'identifyUserV2', - mapping: defaultValues(identifyUserV2.fields), - type: 'automatic' - }, - { - name: 'Viewed Page', - subscribe: 'type = "page"', - partnerAction: 'viewedPageV2', - mapping: defaultValues(viewedPageV2.fields), - type: 'automatic' - } - ], - settings: { - orgId: { - description: 'The organization ID for FullStory.', - label: 'FS Org', - type: 'string', - required: true - }, - debug: { - description: 'Enables FullStory debug mode.', - label: 'Debug mode', - type: 'boolean', - required: false, - default: false - }, - recordOnlyThisIFrame: { - description: 'Enables FullStory inside an iframe.', - label: 'Capture only this iFrame', - type: 'boolean', - required: false, - default: false - } - }, - actions: { - trackEvent, - trackEventV2, - identifyUser, - identifyUserV2, - viewedPage, - viewedPageV2 - }, - initialize: async ({ settings }, dependencies) => { - initFullStory(settings) - await dependencies.resolveWhen(() => Object.prototype.hasOwnProperty.call(window, 'FS'), 100) - return window.FS - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/fullstory/src/trackEvent/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/trackEvent/generated-types.ts deleted file mode 100644 index 6ec21ec140..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/trackEvent/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The name of the event. - */ - name: string - /** - * A JSON object containing additional information about the event that will be indexed by FullStory. - */ - properties?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/fullstory/src/trackEvent/index.ts b/packages/browser-destinations/destinations/fullstory/src/trackEvent/index.ts deleted file mode 100644 index e47292cb55..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/trackEvent/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { FS } from '../types' -import { segmentEventSource } from '..' - -const action: BrowserActionDefinition = { - title: 'Track Event', - description: 'Track events', - platform: 'web', - defaultSubscription: 'type = "track"', - fields: { - name: { - description: 'The name of the event.', - label: 'Name', - required: true, - type: 'string', - default: { - '@path': '$.event' - } - }, - properties: { - description: 'A JSON object containing additional information about the event that will be indexed by FullStory.', - label: 'Properties', - required: false, - type: 'object', - default: { - '@path': '$.properties' - } - } - }, - perform: (FS, event) => { - FS.event(event.payload.name, event.payload.properties ?? {}, segmentEventSource) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/fullstory/src/trackEventV2/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/trackEventV2/generated-types.ts deleted file mode 100644 index 6ec21ec140..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/trackEventV2/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The name of the event. - */ - name: string - /** - * A JSON object containing additional information about the event that will be indexed by FullStory. - */ - properties?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/fullstory/src/trackEventV2/index.ts b/packages/browser-destinations/destinations/fullstory/src/trackEventV2/index.ts deleted file mode 100644 index 50f2f7b2c0..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/trackEventV2/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { FS } from '../types' -import { segmentEventSource } from '..' - -const action: BrowserActionDefinition = { - title: 'Track Event V2', - description: 'Track events', - platform: 'web', - defaultSubscription: 'type = "track"', - fields: { - name: { - description: 'The name of the event.', - label: 'Name', - required: true, - type: 'string', - default: { - '@path': '$.event' - } - }, - properties: { - description: 'A JSON object containing additional information about the event that will be indexed by FullStory.', - label: 'Properties', - required: false, - type: 'object', - default: { - '@path': '$.properties' - } - } - }, - perform: (FS, event) => { - FS( - 'trackEvent', - { - name: event.payload.name, - properties: event.payload.properties ?? {} - }, - segmentEventSource - ) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/fullstory/src/types.ts b/packages/browser-destinations/destinations/fullstory/src/types.ts deleted file mode 100644 index 7a23e1a0e5..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { FullStory, init as initFullStory } from '@fullstory/browser' - -export type FS = typeof FullStory -export { FullStory, initFullStory } diff --git a/packages/browser-destinations/destinations/fullstory/src/viewedPage/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/viewedPage/generated-types.ts deleted file mode 100644 index fa90a6ee12..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/viewedPage/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The name of the page that was viewed. - */ - pageName?: string - /** - * The properties of the page that was viewed. - */ - properties?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/fullstory/src/viewedPage/index.ts b/packages/browser-destinations/destinations/fullstory/src/viewedPage/index.ts deleted file mode 100644 index c4949b8f06..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/viewedPage/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { FS } from '../types' -import { segmentEventSource } from '..' - -const action: BrowserActionDefinition = { - title: 'Viewed Page', - description: 'Sets page properties events', - defaultSubscription: 'type = "page"', - platform: 'web', - fields: { - pageName: { - type: 'string', - required: false, - description: 'The name of the page that was viewed.', - label: 'Page Name', - default: { - '@if': { - exists: { '@path': '$.category' }, - then: { '@path': '$.category' }, - else: { '@path': '$.name' } - } - } - }, - properties: { - type: 'object', - required: false, - description: 'The properties of the page that was viewed.', - label: 'Properties', - default: { - '@path': '$.properties' - } - } - }, - perform: (FS, event) => { - if (event.payload.pageName) { - FS.setVars('page', { pageName: event.payload.pageName, ...event.payload.properties }, segmentEventSource) - } else if (event.payload.properties) { - FS.setVars('page', event.payload.properties, segmentEventSource) - } - } -} - -export default action diff --git a/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/generated-types.ts deleted file mode 100644 index fa90a6ee12..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The name of the page that was viewed. - */ - pageName?: string - /** - * The properties of the page that was viewed. - */ - properties?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/index.ts b/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/index.ts deleted file mode 100644 index a531c0df22..0000000000 --- a/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { FS } from '../types' -import { segmentEventSource } from '..' - -const action: BrowserActionDefinition = { - title: 'Viewed Page V2', - description: 'Sets page properties', - defaultSubscription: 'type = "page"', - platform: 'web', - fields: { - pageName: { - type: 'string', - required: false, - description: 'The name of the page that was viewed.', - label: 'Page Name', - default: { - '@if': { - exists: { '@path': '$.category' }, - then: { '@path': '$.category' }, - else: { '@path': '$.name' } - } - } - }, - properties: { - type: 'object', - required: false, - description: 'The properties of the page that was viewed.', - label: 'Properties', - default: { - '@path': '$.properties' - } - } - }, - perform: (FS, event) => { - const properties: object = event.payload.pageName - ? { pageName: event.payload.pageName, ...event.payload.properties } - : { ...event.payload.properties } - - FS( - 'setProperties', - { - type: 'page', - properties - }, - segmentEventSource - ) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/fullstory/tsconfig.json b/packages/browser-destinations/destinations/fullstory/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/fullstory/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/package.json b/packages/browser-destinations/destinations/google-analytics-4-web/package.json deleted file mode 100644 index afc8cf6076..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-google-analytics-4", - "version": "1.54.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/actions-core": "^3.116.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/addPaymentInfo.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/addPaymentInfo.test.ts deleted file mode 100644 index 9a25125aa5..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/addPaymentInfo.test.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'addPaymentInfo', - name: 'Add Payment Info', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - coupon: { - '@path': '$.properties.coupon' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.addPaymentInfo', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let addPaymentInfoEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - addPaymentInfoEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 addPaymentInfo Event when send to is false', async () => { - const context = new Context({ - event: 'Payment Info Entered', - type: 'track', - properties: { - currency: 'USD', - value: 10, - coupon: 'SUMMER_123', - payment_method: 'Credit Card', - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await addPaymentInfoEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('add_payment_info'), - expect.objectContaining({ - coupon: 'SUMMER_123', - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) - - test('GA4 addPaymentInfo Event when send to is true', async () => { - const context = new Context({ - event: 'Payment Info Entered', - type: 'track', - properties: { - currency: 'USD', - value: 10, - coupon: 'SUMMER_123', - payment_method: 'Credit Card', - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await addPaymentInfoEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('add_payment_info'), - expect.objectContaining({ - coupon: 'SUMMER_123', - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: settings.measurementID - }) - ) - }) - - test('GA4 addPaymentInfo Event when send to is undefined', async () => { - const context = new Context({ - event: 'Payment Info Entered', - type: 'track', - properties: { - currency: 'USD', - value: 10, - coupon: 'SUMMER_123', - payment_method: 'Credit Card', - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await addPaymentInfoEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('add_payment_info'), - expect.objectContaining({ - coupon: 'SUMMER_123', - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/addToCart.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/addToCart.test.ts deleted file mode 100644 index 024f34742c..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/addToCart.test.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'addToCart', - name: 'Add To Cart', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.addToCart', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let addToCartEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - addToCartEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 addToCart Event when send to is false', async () => { - const context = new Context({ - event: 'Add To Cart', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await addToCartEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('add_to_cart'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) - test('GA4 addToCart Event when send to is true', async () => { - const context = new Context({ - event: 'Add To Cart', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await addToCartEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('add_to_cart'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: settings.measurementID - }) - ) - }) - - test('GA4 addToCart Event when send to is undefined', async () => { - const context = new Context({ - event: 'Add To Cart', - type: 'track', - properties: { - currency: 'USD', - value: 10, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await addToCartEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('add_to_cart'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/addToWishlist.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/addToWishlist.test.ts deleted file mode 100644 index fdd99f0664..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/addToWishlist.test.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'addToWishlist', - name: 'Add To Wishlist', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.addToWishlist', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let addToWishlistEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - addToWishlistEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('Track call without parameters when send to is false', async () => { - const context = new Context({ - event: 'Add To Wishlist', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await addToWishlistEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('add_to_wishlist'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) - - test('Track call without parameters when send to is true', async () => { - const context = new Context({ - event: 'Add To Wishlist', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await addToWishlistEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('add_to_wishlist'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: settings.measurementID - }) - ) - }) - - test('Track call without parameters when send to is undefined', async () => { - const context = new Context({ - event: 'Add To Wishlist', - type: 'track', - properties: { - currency: 'USD', - value: 10, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await addToWishlistEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('add_to_wishlist'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/beginCheckout.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/beginCheckout.test.ts deleted file mode 100644 index 23d72e68e1..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/beginCheckout.test.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'beginCheckout', - name: 'Begin Checkout', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - coupon: { - '@path': '$.properties.coupon' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.beginCheckout', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let beginCheckoutEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - beginCheckoutEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 beginCheckout Event when send to is false', async () => { - const context = new Context({ - event: 'Begin Checkout', - type: 'track', - properties: { - currency: 'USD', - value: 10, - coupon: 'SUMMER_123', - payment_method: 'Credit Card', - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await beginCheckoutEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('begin_checkout'), - expect.objectContaining({ - coupon: 'SUMMER_123', - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) - test('GA4 beginCheckout Event when send to is true', async () => { - const context = new Context({ - event: 'Begin Checkout', - type: 'track', - properties: { - currency: 'USD', - value: 10, - coupon: 'SUMMER_123', - payment_method: 'Credit Card', - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await beginCheckoutEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('begin_checkout'), - expect.objectContaining({ - coupon: 'SUMMER_123', - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: settings.measurementID - }) - ) - }) - test('GA4 beginCheckout Event when send to is undefined', async () => { - const context = new Context({ - event: 'Begin Checkout', - type: 'track', - properties: { - currency: 'USD', - value: 10, - coupon: 'SUMMER_123', - payment_method: 'Credit Card', - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await beginCheckoutEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('begin_checkout'), - expect.objectContaining({ - coupon: 'SUMMER_123', - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/customEvent.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/customEvent.test.ts deleted file mode 100644 index c155cbcc89..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/customEvent.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'customEvent', - name: 'Custom Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - name: { - '@path': '$.event' - }, - send_to: { - '@path': '$.properties.send_to' - }, - params: { - '@path': '$.properties.params' - } - } - } -] - -describe('GoogleAnalytics4Web.customEvent', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: GA - let customEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - customEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 customEvent Event when send_to is false', async () => { - const context = new Context({ - event: 'Custom Event', - type: 'track', - properties: { - send_to: false, - params: [ - { - paramOne: 'test123', - paramTwo: 'test123', - paramThree: 123 - } - ] - } - }) - await customEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('Custom_Event'), - expect.objectContaining({ - send_to: 'default', - ...[{ paramOne: 'test123', paramThree: 123, paramTwo: 'test123' }] - }) - ) - }) - - test('GA4 customEvent Event when send_to is undefined', async () => { - const context = new Context({ - event: 'Custom Event', - type: 'track', - properties: { - params: [ - { - paramOne: 'test123', - paramTwo: 'test123', - paramThree: 123 - } - ] - } - }) - await customEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('Custom_Event'), - expect.objectContaining({ - send_to: 'default', - ...[{ paramOne: 'test123', paramThree: 123, paramTwo: 'test123' }] - }) - ) - }) - - test('GA4 customEvent Event when send_to is true', async () => { - const context = new Context({ - event: 'Custom Event', - type: 'track', - properties: { - params: [ - { - paramOne: 'test123', - paramTwo: 'test123', - paramThree: 123 - } - ], - send_to: true - } - }) - await customEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('Custom_Event'), - expect.objectContaining({ - send_to: settings.measurementID, - ...[{ paramOne: 'test123', paramThree: 123, paramTwo: 'test123' }] - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/generateLead.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/generateLead.test.ts deleted file mode 100644 index f334f4df38..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/generateLead.test.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'generateLead', - name: 'Generate Leaad', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - send_to: { - '@path': '$.properties.send_to' - } - } - } -] - -describe('GoogleAnalytics4Web.generateLead', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let generateLeadEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - generateLeadEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 generateLead Event when send to is false', async () => { - const context = new Context({ - event: 'Generate Lead', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: false - } - }) - await generateLeadEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('generate_lead'), - expect.objectContaining({ - currency: 'USD', - value: 10, - send_to: 'default' - }) - ) - }) - test('GA4 generateLead Event when send to is true', async () => { - const context = new Context({ - event: 'Generate Lead', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: true - } - }) - await generateLeadEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('generate_lead'), - expect.objectContaining({ - currency: 'USD', - value: 10, - send_to: settings.measurementID - }) - ) - }) - test('GA4 generateLead Event when send to is undefined', async () => { - const context = new Context({ - event: 'Generate Lead', - type: 'track', - properties: { - currency: 'USD', - value: 10 - } - }) - await generateLeadEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('generate_lead'), - expect.objectContaining({ - currency: 'USD', - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/login.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/login.test.ts deleted file mode 100644 index b50577a251..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/login.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'login', - name: 'Login', - enabled: true, - subscribe: 'type = "track"', - mapping: { - method: { - '@path': '$.properties.method' - }, - send_to: { - '@path': '$.properties.send_to' - } - } - } -] - -describe('GoogleAnalytics4Web.login', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: GA - let loginEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - loginEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 login Event when send to is false', async () => { - const context = new Context({ - event: 'Login', - type: 'track', - properties: { - method: 'Google', - send_to: false - } - }) - await loginEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('login'), - expect.objectContaining({ - method: 'Google', - send_to: 'default' - }) - ) - }) - test('GA4 login Event when send to is true', async () => { - const context = new Context({ - event: 'Login', - type: 'track', - properties: { - method: 'Google', - send_to: true - } - }) - await loginEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('login'), - expect.objectContaining({ - method: 'Google', - send_to: settings.measurementID - }) - ) - }) - - test('GA4 login Event when send to is undefined', async () => { - const context = new Context({ - event: 'Login', - type: 'track', - properties: { - method: 'Google' - } - }) - await loginEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('login'), - expect.objectContaining({ - method: 'Google', - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/purchase.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/purchase.test.ts deleted file mode 100644 index 37d2d0aec7..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/purchase.test.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'purchase', - name: 'Purchase', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - coupon: { - '@path': '$.properties.coupon' - }, - transaction_id: { - '@path': '$.properties.transaction_id' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.purchase', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let purchaseEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - purchaseEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 purchase Event when send to is false', async () => { - const context = new Context({ - event: 'Purchase', - type: 'track', - properties: { - currency: 'USD', - value: 10, - transaction_id: 12321, - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await purchaseEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('purchase'), - expect.objectContaining({ - currency: 'USD', - transaction_id: 12321, - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) - test('GA4 purchase Event when send to is true', async () => { - const context = new Context({ - event: 'Purchase', - type: 'track', - properties: { - currency: 'USD', - value: 10, - transaction_id: 12321, - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await purchaseEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('purchase'), - expect.objectContaining({ - currency: 'USD', - transaction_id: 12321, - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: settings.measurementID - }) - ) - }) - - test('GA4 purchase Event when send to is undefined', async () => { - const context = new Context({ - event: 'Purchase', - type: 'track', - properties: { - currency: 'USD', - value: 10, - transaction_id: 12321, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await purchaseEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('purchase'), - expect.objectContaining({ - currency: 'USD', - transaction_id: 12321, - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/refund.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/refund.test.ts deleted file mode 100644 index 3ebf3d5fa1..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/refund.test.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'refund', - name: 'refund', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - send_to: { - '@path': '$.properties.send_to' - }, - coupon: { - '@path': '$.properties.coupon' - }, - transaction_id: { - '@path': '$.properties.transaction_id' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.refund', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let refundEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - refundEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 Refund Event when send to is false', async () => { - const context = new Context({ - event: 'Refund', - type: 'track', - properties: { - currency: 'USD', - value: 10, - transaction_id: 12321, - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await refundEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('refund'), - expect.objectContaining({ - currency: 'USD', - transaction_id: 12321, - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) - test('GA4 Refund Event when send to is true', async () => { - const context = new Context({ - event: 'Refund', - type: 'track', - properties: { - currency: 'USD', - value: 10, - transaction_id: 12321, - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await refundEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('refund'), - expect.objectContaining({ - currency: 'USD', - transaction_id: 12321, - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: settings.measurementID - }) - ) - }) - test('GA4 Refund Event when send to is undefined', async () => { - const context = new Context({ - event: 'Refund', - type: 'track', - properties: { - currency: 'USD', - value: 10, - transaction_id: 12321, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - await refundEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('refund'), - expect.objectContaining({ - currency: 'USD', - transaction_id: 12321, - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/removeFromCart.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/removeFromCart.test.ts deleted file mode 100644 index 2ecdaa5f20..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/removeFromCart.test.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'removeFromCart', - name: 'Remove from cart', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - coupon: { - '@path': '$.properties.coupon' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.removeFromCart', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let removeFromCartEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - removeFromCartEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 removeFromCart Event when send to is false', async () => { - const context = new Context({ - event: 'Remove from Cart', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await removeFromCartEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('remove_from_cart'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) - test('GA4 removeFromCart Event when send to is true', async () => { - const context = new Context({ - event: 'Remove from Cart', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await removeFromCartEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('remove_from_cart'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: settings.measurementID - }) - ) - }) - - test('GA4 removeFromCart Event when send to is undefined', async () => { - const context = new Context({ - event: 'Remove from Cart', - type: 'track', - properties: { - currency: 'USD', - value: 10, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await removeFromCartEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('remove_from_cart'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/search.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/search.test.ts deleted file mode 100644 index a7b1c19c33..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/search.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'search', - name: 'search', - enabled: true, - subscribe: 'type = "track"', - mapping: { - search_term: { - '@path': '$.properties.search_term' - }, - send_to: { - '@path': '$.properties.send_to' - } - } - } -] - -describe('GoogleAnalytics4Web.search', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let searchEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - searchEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 search Event when send to is false', async () => { - const context = new Context({ - event: 'search', - type: 'track', - properties: { - search_term: 'Monopoly: 3rd Edition', - send_to: false - } - }) - - await searchEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('search'), - expect.objectContaining({ - search_term: 'Monopoly: 3rd Edition', - send_to: 'default' - }) - ) - }) - test('GA4 search Event when send to is true', async () => { - const context = new Context({ - event: 'search', - type: 'track', - properties: { - search_term: 'Monopoly: 3rd Edition', - send_to: true - } - }) - - await searchEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('search'), - expect.objectContaining({ - search_term: 'Monopoly: 3rd Edition', - send_to: settings.measurementID - }) - ) - }) - test('GA4 search Event when send to is undefined', async () => { - const context = new Context({ - event: 'search', - type: 'track', - properties: { - search_term: 'Monopoly: 3rd Edition' - } - }) - - await searchEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('search'), - expect.objectContaining({ - search_term: 'Monopoly: 3rd Edition', - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/selectItem.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/selectItem.test.ts deleted file mode 100644 index 345a2884ce..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/selectItem.test.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'selectItem', - name: 'Select Item', - enabled: true, - subscribe: 'type = "track"', - mapping: { - item_list_id: { - '@path': '$.properties.item_list_id' - }, - item_list_name: { - '@path': '$.properties.item_list_name' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.selectItem', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let selectItemEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - selectItemEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 selectItem Event when send to is false', async () => { - const context = new Context({ - event: 'Select Item', - type: 'track', - properties: { - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await selectItemEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('select_item'), - expect.objectContaining({ - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: 'default' - }) - ) - }) - test('GA4 selectItem Event when send to is true', async () => { - const context = new Context({ - event: 'Select Item', - type: 'track', - properties: { - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await selectItemEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('select_item'), - expect.objectContaining({ - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: settings.measurementID - }) - ) - }) - - test('GA4 selectItem Event when send to is undefined', async () => { - const context = new Context({ - event: 'Select Item', - type: 'track', - properties: { - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await selectItemEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('select_item'), - expect.objectContaining({ - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/selectPromotion.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/selectPromotion.test.ts deleted file mode 100644 index c35a910668..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/selectPromotion.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'selectPromotion', - name: 'Select Promotion', - enabled: true, - subscribe: 'type = "track"', - mapping: { - creative_name: { - '@path': '$.properties.creative_name' - }, - creative_slot: { - '@path': '$.properties.creative_slot' - }, - location_id: { - '@path': '$.properties.location_id' - }, - promotion_id: { - '@path': '$.properties.promotion_id' - }, - promotion_name: { - '@path': '$.properties.promotion_name' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.selectPromotion', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let selectPromotionEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - selectPromotionEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 selectPromotion Event when send to is false', async () => { - const context = new Context({ - event: 'Select Promotion', - type: 'track', - properties: { - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await selectPromotionEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('select_promotion'), - expect.objectContaining({ - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: 'default' - }) - ) - }) - test('GA4 selectPromotion Event when send to is true', async () => { - const context = new Context({ - event: 'Select Promotion', - type: 'track', - properties: { - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await selectPromotionEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('select_promotion'), - expect.objectContaining({ - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: settings.measurementID - }) - ) - }) - - test('GA4 selectPromotion Event when send to is undefined', async () => { - const context = new Context({ - event: 'Select Promotion', - type: 'track', - properties: { - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await selectPromotionEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('select_promotion'), - expect.objectContaining({ - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/setConfigurationFields.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/setConfigurationFields.test.ts deleted file mode 100644 index feca9da7d3..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/setConfigurationFields.test.ts +++ /dev/null @@ -1,809 +0,0 @@ -import googleAnalytics4Web, { destination } from '../index' -import { Analytics, Context } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' - -let mockGtag: GA -let setConfigurationEvent: any -const subscriptions: Subscription[] = [ - { - partnerAction: 'setConfigurationFields', - name: 'Set Configuration Fields', - enabled: true, - subscribe: 'type = "page"', - mapping: { - ads_storage_consent_state: { - '@path': '$.properties.ads_storage_consent_state' - }, - analytics_storage_consent_state: { - '@path': '$.properties.analytics_storage_consent_state' - }, - screen_resolution: { - '@path': '$.properties.screen_resolution' - }, - user_id: { - '@path': '$.properties.user_id' - }, - page_title: { - '@path': '$.properties.page_title' - }, - page_referrer: { - '@path': '$.properties.page_referrer' - }, - language: { - '@path': '$.properties.language' - }, - content_group: { - '@path': '$.properties.content_group' - }, - campaign_content: { - '@path': '$.properties.campaign_content' - }, - campaign_id: { - '@path': '$.properties.campaign_id' - }, - campaign_medium: { - '@path': '$.properties.campaign_medium' - }, - campaign_name: { - '@path': '$.properties.campaign_name' - }, - campaign_source: { - '@path': '$.properties.campaign_source' - }, - campaign_term: { - '@path': '$.properties.campaign_term' - }, - ad_user_data_consent_state: { - '@path': '$.properties.ad_user_data_consent_state' - }, - ad_personalization_consent_state: { - '@path': '$.properties.ad_personalization_consent_state' - }, - send_page_view: { - '@path': '$.properties.send_page_view' - } - } - } -] - -describe('Set Configuration Fields action', () => { - const defaultSettings: Settings = { - enableConsentMode: false, - measurementID: 'G-XXXXXXXXXX', - allowAdPersonalizationSignals: false, - allowGoogleSignals: false, - cookieDomain: 'auto', - cookieExpirationInSeconds: 63072000, - cookieUpdate: true, - pageView: true - } - beforeEach(async () => { - jest.restoreAllMocks() - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...defaultSettings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGtag = jest.fn() - return Promise.resolve(mockGtag) - }) - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - }) - - it('should configure consent when consent mode is enabled', async () => { - defaultSettings.enableConsentMode = true - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...defaultSettings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - ads_storage_consent_state: 'granted', - analytics_storage_consent_state: 'denied' - } - }) - - setConfigurationEvent.page?.(context) - - expect(mockGtag).toHaveBeenCalledWith('consent', 'update', { - ad_storage: 'granted', - analytics_storage: 'denied' - }) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true - }) - }) - it('should configure cookie expiry time other then default value', async () => { - const settings = { - ...defaultSettings, - cookieExpirationInSeconds: 500 - } - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: {} - }) - - setConfigurationEvent.page?.(context) - - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - cookie_expires: 500 - }) - }) - it('should configure cookie domain other then default value', async () => { - const settings = { - ...defaultSettings, - cookieDomain: 'example.com' - } - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: {} - }) - - setConfigurationEvent.page?.(context) - - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - cookie_domain: 'example.com' - }) - }) - it('should configure cookie prefix other then default value', async () => { - const settings = { - ...defaultSettings, - cookiePrefix: 'stage' - } - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: {} - }) - - setConfigurationEvent.page?.(context) - - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - cookie_prefix: 'stage' - }) - }) - it('should configure cookie path other then default value', async () => { - const settings = { - ...defaultSettings, - cookiePath: '/home' - } - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: {} - }) - - setConfigurationEvent.page?.(context) - - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - cookie_path: '/home' - }) - }) - it('should configure cookie update other then default value', async () => { - const settings = { - ...defaultSettings, - cookieUpdate: false - } - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: {} - }) - - setConfigurationEvent.page?.(context) - - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - cookie_update: false - }) - }) - it('should not configure consent when consent mode is disabled', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: false - } - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: {} - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true - }) - }) - it('should update config if payload has screen resolution', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - screen_resolution: '800*600' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - screen_resolution: '800*600' - }) - }) - it('should update config if payload has user_id', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - user_id: 'segment-123' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - user_id: 'segment-123' - }) - }) - it('should update config if payload has page_title', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - page_title: 'User Registration Page' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - page_title: 'User Registration Page' - }) - }) - it('should update config if payload has language', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - language: 'EN' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - language: 'EN' - }) - }) - it('should update config if payload has content_group', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - content_group: '/home/login' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - content_group: '/home/login' - }) - }) - it('should update config if payload has campaign_term', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - campaign_term: 'running+shoes' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - campaign_term: 'running+shoes' - }) - }) - it('should update config if payload has campaign_source', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - campaign_source: 'google' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - campaign_source: 'google' - }) - }) - it('should update config if payload has campaign_name', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - campaign_name: 'spring_sale' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - campaign_name: 'spring_sale' - }) - }) - it('should update config if payload has campaign_medium', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - campaign_medium: 'cpc' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - campaign_medium: 'cpc' - }) - }) - it('should update config if payload has campaign_id', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - campaign_id: 'abc.123' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - campaign_id: 'abc.123' - }) - }) - it('should update config if payload has campaign_content', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - campaign_content: 'logolink' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true, - campaign_content: 'logolink' - }) - }) - - it('pageView is true and send_page_view is true -> nothing', async () => { - const settings = { - ...defaultSettings, - pageView: true - } - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: true - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false - }) - }) - it('pageView is true and send_page_view is false -> false', async () => { - const settings = { - ...defaultSettings, - pageView: true - } - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: false - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: false - }) - }) - it('pageView is true and send_page_view is undefined -> true', async () => { - const settings = { - ...defaultSettings, - pageView: true - } - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: undefined - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true - }) - }) - - it('pageView is false and send_page_view is true -> true', async () => { - const settings = { - ...defaultSettings, - pageView: false - } - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: true - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true - }) - }) - - it('pageView is false and send_page_view is false -> false', async () => { - const settings = { - ...defaultSettings, - pageView: false - } - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: false - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: false - }) - }) - - it('pageView is false and send_page_view is undefined -> false', async () => { - const settings = { - ...defaultSettings, - pageView: false - } - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: undefined - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: false - }) - }) - - it('pageView is undefined and send_page_view is undefined -> true', async () => { - const settings = { - ...defaultSettings, - pageView: undefined - } - - const [setConfigurationEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - setConfigurationEvent = setConfigurationEventPlugin - await setConfigurationEventPlugin.load(Context.system(), {} as Analytics) - - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: undefined - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true - }) - }) - - it('should update consent if payload has ad_user_data_consent_state granted', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - ad_user_data_consent_state: 'granted' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('consent', 'update', { - ad_user_data: 'granted' - }) - }) - - it('should update consent if payload has ad_user_data_consent_state denied', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - ad_user_data_consent_state: 'denied' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('consent', 'update', { - ad_user_data: 'denied' - }) - }) - - it('should update consent if payload has ad_user_data_consent_state undefined', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - ad_user_data_consent_state: undefined - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('consent', 'update', {}) - }) - - it('should update consent if payload has ad_personalization_consent_state granted', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - ad_personalization_consent_state: 'granted' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('consent', 'update', { - ad_personalization: 'granted' - }) - }) - it('should update consent if payload has ad_personalization_consent_state denied', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - ad_personalization_consent_state: 'denied' - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('consent', 'update', { - ad_personalization: 'denied' - }) - }) - it('should update consent if payload has ad_personalization_consent_state undefined', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - ad_personalization_consent_state: undefined - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('consent', 'update', {}) - }) - it('should update config if payload has send_page_view undefined', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: undefined - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: true - }) - }) - it('should update config if payload has send_page_view true', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: true - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false - }) - }) - - it('should update config if payload has send_page_view false', () => { - const context = new Context({ - event: 'setConfigurationFields', - type: 'page', - properties: { - send_page_view: false - } - }) - - setConfigurationEvent.page?.(context) - expect(mockGtag).toHaveBeenCalledWith('config', 'G-XXXXXXXXXX', { - allow_ad_personalization_signals: false, - allow_google_signals: false, - send_page_view: false - }) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/signUp.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/signUp.test.ts deleted file mode 100644 index e17079d77f..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/signUp.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'signUp', - name: 'signUp', - enabled: true, - subscribe: 'type = "track"', - mapping: { - method: { - '@path': '$.properties.method' - }, - send_to: { - '@path': '$.properties.send_to' - } - } - } -] - -describe('GoogleAnalytics4Web.signUp', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let signUpEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - signUpEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 signUp Event when send to is false', async () => { - const context = new Context({ - event: 'signUp', - type: 'track', - properties: { - method: 'Google', - send_to: false - } - }) - - await signUpEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('sign_up'), - expect.objectContaining({ method: 'Google', send_to: 'default' }) - ) - }) - test('GA4 signUp Event when send to is true', async () => { - const context = new Context({ - event: 'signUp', - type: 'track', - properties: { - method: 'Google', - send_to: true - } - }) - - await signUpEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('sign_up'), - expect.objectContaining({ method: 'Google', send_to: settings.measurementID }) - ) - }) - - test('GA4 signUp Event when send to is undefined', async () => { - const context = new Context({ - event: 'signUp', - type: 'track', - properties: { - method: 'Google' - } - }) - - await signUpEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('sign_up'), - expect.objectContaining({ method: 'Google', send_to: 'default' }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewCart.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewCart.test.ts deleted file mode 100644 index da2c7c52da..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewCart.test.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'viewCart', - name: 'View Cart', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.viewCart', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let viewCartEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - viewCartEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 viewCart Event when send to is false', async () => { - const context = new Context({ - event: 'View Cart', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewCartEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_cart'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) - test('GA4 viewCart Event when send to is true', async () => { - const context = new Context({ - event: 'View Cart', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewCartEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_cart'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: settings.measurementID - }) - ) - }) - - test('GA4 viewCart Event when send to is false', async () => { - const context = new Context({ - event: 'View Cart', - type: 'track', - properties: { - currency: 'USD', - value: 10, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewCartEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_cart'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewItem.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewItem.test.ts deleted file mode 100644 index 08d3ab4706..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewItem.test.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'viewItem', - name: 'View Item', - enabled: true, - subscribe: 'type = "track"', - mapping: { - currency: { - '@path': '$.properties.currency' - }, - value: { - '@path': '$.properties.value' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.viewItem', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let viewItemEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - viewItemEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 viewItem Event when send to is false', async () => { - const context = new Context({ - event: 'View Item', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewItemEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_item'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) - test('GA4 viewItem Event when send to is true', async () => { - const context = new Context({ - event: 'View Item', - type: 'track', - properties: { - currency: 'USD', - value: 10, - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewItemEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_item'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: settings.measurementID - }) - ) - }) - test('GA4 viewItem Event when send to is undefined', async () => { - const context = new Context({ - event: 'View Item', - type: 'track', - properties: { - currency: 'USD', - value: 10, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewItemEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_item'), - expect.objectContaining({ - currency: 'USD', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - value: 10, - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewItemList.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewItemList.test.ts deleted file mode 100644 index b9ec9bd1ad..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewItemList.test.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'viewItemList', - name: 'View Item List', - enabled: true, - subscribe: 'type = "track"', - mapping: { - item_list_id: { - '@path': '$.properties.item_list_id' - }, - item_list_name: { - '@path': '$.properties.item_list_name' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.viewItemList', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let viewItemListEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - viewItemListEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 viewItemList Event when send to is false', async () => { - const context = new Context({ - event: 'View Item List', - type: 'track', - properties: { - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewItemListEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_item_list'), - expect.objectContaining({ - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: 'default' - }) - ) - }) - - test('GA4 viewItemList Event when send to is true', async () => { - const context = new Context({ - event: 'View Item List', - type: 'track', - properties: { - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewItemListEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_item_list'), - expect.objectContaining({ - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: settings.measurementID - }) - ) - }) - - test('GA4 viewItemList Event when send to is undefined', async () => { - const context = new Context({ - event: 'View Item List', - type: 'track', - properties: { - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewItemListEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_item_list'), - expect.objectContaining({ - item_list_id: 12321, - item_list_name: 'Monopoly: 3rd Edition', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewPromotion.test.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewPromotion.test.ts deleted file mode 100644 index 3e5356242b..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/__tests__/viewPromotion.test.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleAnalytics4Web, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'viewPromotion', - name: 'Select Promotion', - enabled: true, - subscribe: 'type = "track"', - mapping: { - creative_name: { - '@path': '$.properties.creative_name' - }, - creative_slot: { - '@path': '$.properties.creative_slot' - }, - location_id: { - '@path': '$.properties.location_id' - }, - promotion_id: { - '@path': '$.properties.promotion_id' - }, - promotion_name: { - '@path': '$.properties.promotion_name' - }, - send_to: { - '@path': '$.properties.send_to' - }, - items: [ - { - item_name: { - '@path': `$.properties.products.0.name` - }, - item_id: { - '@path': `$.properties.products.0.product_id` - }, - currency: { - '@path': `$.properties.products.0.currency` - }, - price: { - '@path': `$.properties.products.0.price` - }, - quantity: { - '@path': `$.properties.products.0.quantity` - } - } - ] - } - } -] - -describe('GoogleAnalytics4Web.viewPromotion', () => { - const settings = { - measurementID: 'test123' - } - - let mockGA4: typeof gtag - let viewPromotionEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleAnalytics4Web({ - ...settings, - subscriptions - }) - viewPromotionEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGA4 = jest.fn() - return Promise.resolve(mockGA4) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('GA4 viewPromotion Event when send to is false', async () => { - const context = new Context({ - event: 'Select Promotion', - type: 'track', - properties: { - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - send_to: false, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewPromotionEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_promotion'), - expect.objectContaining({ - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: 'default' - }) - ) - }) - test('GA4 viewPromotion Event when send to is true', async () => { - const context = new Context({ - event: 'Select Promotion', - type: 'track', - properties: { - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - send_to: true, - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewPromotionEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_promotion'), - expect.objectContaining({ - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: settings.measurementID - }) - ) - }) - test('GA4 viewPromotion Event when send to is undefined', async () => { - const context = new Context({ - event: 'Select Promotion', - type: 'track', - properties: { - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - products: [ - { - product_id: '12345', - name: 'Monopoly: 3rd Edition', - currency: 'USD' - } - ] - } - }) - - await viewPromotionEvent.track?.(context) - - expect(mockGA4).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('view_promotion'), - expect.objectContaining({ - creative_name: 'summer_banner2', - creative_slot: 'featured_app_1', - location_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - promotion_id: 'P_12345', - promotion_name: 'Summer Sale', - items: [{ currency: 'USD', item_id: '12345', item_name: 'Monopoly: 3rd Edition' }], - send_to: 'default' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/addPaymentInfo/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/addPaymentInfo/generated-types.ts deleted file mode 100644 index c083cd3a00..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/addPaymentInfo/generated-types.ts +++ /dev/null @@ -1,122 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * The monetary value of the event. - */ - value?: number - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * The chosen method of payment. - */ - payment_type?: string - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/addPaymentInfo/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/addPaymentInfo/index.ts deleted file mode 100644 index b4d891e3b8..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/addPaymentInfo/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { - user_id, - user_properties, - currency, - value, - coupon, - payment_type, - items_multi_products, - params, - send_to -} from '../ga4-properties' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Add Payment Info', - description: 'Send event when a user submits their payment information', - defaultSubscription: 'type = "track" and event = "Payment Info Entered"', - platform: 'web', - fields: { - user_id: { ...user_id }, - currency: { ...currency }, - value: { ...value }, - coupon: { ...coupon }, - payment_type: { ...payment_type }, - items: { - ...items_multi_products, - required: true - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'add_payment_info', { - currency: payload.currency, - value: payload.value, - coupon: payload.coupon, - payment_type: payload.payment_type, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/addToCart/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/addToCart/generated-types.ts deleted file mode 100644 index 93061827ac..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/addToCart/generated-types.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The monetary value of the event. - */ - value?: number - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/addToCart/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/addToCart/index.ts deleted file mode 100644 index 359fbdd59c..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/addToCart/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { user_properties, params, value, currency, items_single_products, user_id, send_to } from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'Add to Cart', - description: 'This event signifies that an item was added to a cart for purchase.', - defaultSubscription: 'type = "track" and event = "Product Added"', - platform: 'web', - fields: { - user_id: user_id, - currency: currency, - items: { - ...items_single_products, - required: true - }, - value: value, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'add_to_cart', { - currency: payload.currency, - value: payload.value, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/addToWishlist/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/addToWishlist/generated-types.ts deleted file mode 100644 index b6d8985b27..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/addToWishlist/generated-types.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * The monetary value of the event. - */ - value?: number - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/addToWishlist/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/addToWishlist/index.ts deleted file mode 100644 index f416414283..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/addToWishlist/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { user_properties, params, value, currency, items_single_products, user_id, send_to } from '../ga4-properties' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Add to Wishlist', - description: - 'The event signifies that an item was added to a wishlist. Use this event to identify popular gift items in your app.', - platform: 'web', - defaultSubscription: 'type = "track" and event = "Product Added to Wishlist"', - fields: { - user_id: user_id, - currency: currency, - value: value, - items: { - ...items_single_products, - required: true - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'add_to_wishlist', { - currency: payload.currency, - value: payload.value, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/beginCheckout/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/beginCheckout/generated-types.ts deleted file mode 100644 index 084dee203d..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/beginCheckout/generated-types.ts +++ /dev/null @@ -1,118 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The monetary value of the event. - */ - value?: number - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/beginCheckout/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/beginCheckout/index.ts deleted file mode 100644 index 37cfe3c65d..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/beginCheckout/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { - params, - coupon, - currency, - value, - items_multi_products, - user_id, - user_properties, - send_to -} from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'Begin Checkout', - description: 'This event signifies that a user has begun a checkout.', - defaultSubscription: 'type = "track" and event = "Checkout Started"', - platform: 'web', - fields: { - user_id: user_id, - coupon: { ...coupon, default: { '@path': '$.properties.coupon' } }, - currency: currency, - items: { - ...items_multi_products, - required: true - }, - value: value, - params: params, - user_properties: user_properties, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'begin_checkout', { - currency: payload.currency, - value: payload.value, - coupon: payload.coupon, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/customEvent/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/customEvent/generated-types.ts deleted file mode 100644 index fbab80b0b2..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/customEvent/generated-types.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The unique name of the custom event created in GA4. GA4 does not accept spaces in event names so Segment will replace any spaces with underscores. More information about GA4 event name rules is available in [their docs](https://support.google.com/analytics/answer/10085872?hl=en&ref_topic=9756175#event-name-rules&zippy=%2Cin-this-article.%2Cin-this-article). - */ - name: string - /** - * If true, the event name will be converted to lowercase before sending to Google. Event names are case sensitive in GA4 so enable this setting to avoid distinct events for casing differences. More information about GA4 event name rules is available in [their docs](https://support.google.com/analytics/answer/10085872?hl=en&ref_topic=9756175#event-name-rules&zippy=%2Cin-this-article.%2Cin-this-article). - */ - lowercase?: boolean - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/customEvent/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/customEvent/index.ts deleted file mode 100644 index d711da5953..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/customEvent/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { user_id, user_properties, params, send_to } from '../ga4-properties' - -const normalizeEventName = (name: string, lowercase: boolean | undefined): string => { - name = name.trim() - name = name.replace(/\s/g, '_') - - if (lowercase) { - name = name.toLowerCase() - } - return name -} - -const action: BrowserActionDefinition = { - title: 'Custom Event', - description: 'Send any custom event', - defaultSubscription: 'type = "track"', - platform: 'web', - fields: { - name: { - label: 'Event Name', - description: - 'The unique name of the custom event created in GA4. GA4 does not accept spaces in event names so Segment will replace any spaces with underscores. More information about GA4 event name rules is available in [their docs](https://support.google.com/analytics/answer/10085872?hl=en&ref_topic=9756175#event-name-rules&zippy=%2Cin-this-article.%2Cin-this-article).', - type: 'string', - required: true, - default: { - '@path': '$.event' - } - }, - lowercase: { - label: 'Lowercase Event Name', - description: - 'If true, the event name will be converted to lowercase before sending to Google. Event names are case sensitive in GA4 so enable this setting to avoid distinct events for casing differences. More information about GA4 event name rules is available in [their docs](https://support.google.com/analytics/answer/10085872?hl=en&ref_topic=9756175#event-name-rules&zippy=%2Cin-this-article.%2Cin-this-article).', - type: 'boolean', - default: false - }, - user_id: { ...user_id }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - const event_name = normalizeEventName(payload.name, payload.lowercase) - - gtag('event', event_name, { - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/ga4-properties.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/ga4-properties.ts deleted file mode 100644 index bdbd03d360..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/ga4-properties.ts +++ /dev/null @@ -1,376 +0,0 @@ -import { InputField } from '@segment/actions-core/destination-kit/types' - -export const formatUserProperties = (userProperties: object | undefined): object | undefined => { - if (!userProperties) { - return undefined - } - - let properties = {} - - Object.entries(userProperties).forEach(([key, value]) => { - properties = { ...properties, ...{ [key]: { value: value } } } - }) - - return { user_properties: properties } -} - -export const user_properties: InputField = { - label: 'User Properties', - description: - 'The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. ', - type: 'object', - additionalProperties: true, - defaultObjectUI: 'keyvalue' -} - -export const params: InputField = { - label: 'Event Parameters', - description: 'The event parameters to send to Google Analytics 4.', - type: 'object', - additionalProperties: true, - defaultObjectUI: 'keyvalue' -} -export const user_id: InputField = { - label: 'User ID', - type: 'string', - description: - "A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier." -} - -export const promotion_id: InputField = { - label: 'Promotion ID', - type: 'string', - description: 'The ID of the promotion associated with the event.' -} - -export const promotion_name: InputField = { - label: 'Promotion Name', - type: 'string', - description: 'The name of the promotion associated with the event.' -} - -export const creative_slot: InputField = { - label: 'Creative Slot', - type: 'string', - description: 'The name of the promotional creative slot associated with the event.' -} - -export const creative_name: InputField = { - label: 'Creative Name', - type: 'string', - description: 'The name of the promotional creative.' -} - -export const tax: InputField = { - label: 'Tax', - type: 'number', - description: 'Total tax associated with the transaction.', - default: { - '@path': '$.properties.tax' - } -} - -export const shipping: InputField = { - label: 'Shipping', - type: 'number', - description: 'Shipping cost associated with the transaction.', - default: { - '@path': '$.properties.shipping' - } -} - -export const transaction_id: InputField = { - label: 'Order Id', - type: 'string', - description: 'The unique identifier of a transaction.', - default: { - '@path': '$.properties.order_id' - } -} - -export const affiliation: InputField = { - label: 'Affiliation', - type: 'string', - description: 'Store or affiliation from which this transaction occurred (e.g. Google Store).', - default: { - '@path': '$.properties.affiliation' - } -} - -export const client_id: InputField = { - label: 'Client ID', - description: 'Uniquely identifies a user instance of a web client.', - type: 'string', - required: true, - default: { - '@if': { - exists: { '@path': '$.userId' }, - then: { '@path': '$.userId' }, - else: { '@path': '$.anonymousId' } - } - } -} - -export const currency: InputField = { - label: 'Currency', - type: 'string', - description: 'Currency of the items associated with the event, in 3-letter ISO 4217 format.', - default: { '@path': '$.properties.currency' } -} - -export const value: InputField = { - label: 'Value', - type: 'number', - description: 'The monetary value of the event.', - default: { - '@path': '$.properties.value' - } -} - -export const coupon: InputField = { - label: 'Coupon', - type: 'string', - description: 'Coupon code used for a purchase.' -} - -export const payment_type: InputField = { - label: 'Payment Type', - type: 'string', - description: 'The chosen method of payment.', - default: { - '@path': '$.properties.payment_method' - } -} - -export const method: InputField = { - label: 'Method', - type: 'string', - description: 'The method used to login.', - default: { - '@path': '$.properties.method' - } -} - -export const search_term: InputField = { - label: 'Search Term', - type: 'string', - description: 'The term that was searched for.', - default: { - '@path': `$.properties.query` - } -} - -export const item_list_name: InputField = { - label: 'Item List Name', - description: 'The name of the list in which the item was presented to the user.', - type: 'string', - default: { - '@path': `$.properties.item_list_name` - } -} -export const item_list_id: InputField = { - label: 'Item List Id', - description: 'The ID of the list in which the item was presented to the user.', - type: 'string', - default: { - '@path': `$.properties.item_list_id` - } -} -export const location_id: InputField = { - label: 'Location ID', - type: 'string', - description: 'The ID of the location.', - default: { - '@path': '$.properties.position' - } -} - -export const minimal_items: InputField = { - label: 'Products', - description: 'The list of products purchased.', - type: 'object', - multiple: true, - additionalProperties: true, - properties: { - item_id: { - label: 'Product ID', - type: 'string', - description: 'Identifier for the product being purchased.' - }, - item_name: { - label: 'Name', - type: 'string', - description: 'Name of the product being purchased.' - }, - affiliation: { - label: 'Affiliation', - type: 'string', - description: 'A product affiliation to designate a supplying company or brick and mortar store location.' - }, - coupon: { - label: 'Coupon', - type: 'string', - description: 'Coupon code used for a purchase.' - }, - currency: { - label: 'Currency', - type: 'string', - description: 'Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format.' - }, - discount: { - label: 'Discount', - type: 'number', - description: 'Monetary value of discount associated with a purchase.' - }, - index: { - label: 'Index', - type: 'number', - description: 'The index/position of the item in a list.' - }, - item_brand: { - label: 'Brand', - type: 'string', - description: 'Brand associated with the product.' - }, - item_category: { - label: 'Category', - type: 'string', - description: 'Product category.' - }, - item_category2: { - label: 'Category 2', - type: 'string', - description: 'Product category 2.' - }, - item_category3: { - label: 'Category 3', - type: 'string', - description: 'Product category 3.' - }, - item_category4: { - label: 'Category 4', - type: 'string', - description: 'Product category 4.' - }, - item_category5: { - label: 'Category 5', - type: 'string', - description: 'Product category 5.' - }, - item_list_id: { - label: 'Item List ID', - type: 'string', - description: 'The ID of the list in which the item was presented to the user.' - }, - item_list_name: { - label: 'Item List Name', - type: 'string', - description: 'The name of the list in which the item was presented to the user.' - }, - item_variant: { - label: 'Variant', - type: 'string', - description: 'Variant of the product (e.g. Black).' - }, - location_id: { - label: 'Location ID', - type: 'string', - description: 'The location associated with the item.' - }, - price: { - label: 'Price', - type: 'number', - description: 'Price of the product being purchased, in units of the specified currency parameter.' - }, - quantity: { - label: 'Quantity', - type: 'integer', - description: 'Item quantity.' - } - } -} - -export const items_single_products: InputField = { - ...minimal_items, - default: { - '@arrayPath': [ - '$.properties.products', - { - item_id: { - '@path': '$.product_id' - }, - item_name: { - '@path': '$.name' - }, - affiliation: { - '@path': '$.affiliation' - }, - coupon: { - '@path': '$.coupon' - }, - item_brand: { - '@path': '$.brand' - }, - item_category: { - '@path': '$.category' - }, - item_variant: { - '@path': '$.variant' - }, - price: { - '@path': '$.price' - }, - quantity: { - '@path': '$.quantity' - } - } - ] - } -} -export const items_multi_products: InputField = { - ...minimal_items, - default: { - '@arrayPath': [ - '$.properties.products', - { - item_id: { - '@path': '$.product_id' - }, - item_name: { - '@path': '$.name' - }, - affiliation: { - '@path': '$.affiliation' - }, - coupon: { - '@path': '$.coupon' - }, - index: { - '@path': '$.position' - }, - item_brand: { - '@path': '$.brand' - }, - item_category: { - '@path': '$.category' - }, - item_variant: { - '@path': '$.variant' - }, - price: { - '@path': '$.price' - }, - quantity: { - '@path': '$.quantity' - } - } - ] - } -} -export const send_to: InputField = { - label: 'Send To', - type: 'boolean', - default: true, - description: - 'If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag' -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/ga4-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/ga4-types.ts deleted file mode 100644 index e6595abb74..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/ga4-types.ts +++ /dev/null @@ -1,28 +0,0 @@ -export interface ProductItem { - item_id?: string - item_name?: string - affiliation?: string - coupon?: string - currency?: string - discount?: number - index?: number - item_brand?: string - item_category?: string - item_category2?: string - item_category3?: string - item_category4?: string - item_category5?: string - item_list_id?: string - item_list_name?: string - item_variant?: string - location_id?: string - price?: number - quantity?: number -} - -export interface PromotionProductItem extends ProductItem { - creative_name?: string - creative_slot?: string - promotion_id?: string - promotion_name?: string -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/generateLead/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/generateLead/generated-types.ts deleted file mode 100644 index 744738a197..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/generateLead/generated-types.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * The monetary value of the event. - */ - value?: number - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/generateLead/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/generateLead/index.ts deleted file mode 100644 index c2302fa3b3..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/generateLead/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { user_properties, params, user_id, currency, value, send_to } from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'Generate Lead', - description: - 'Log this event when a lead has been generated to understand the efficacy of your re-engagement campaigns.', - platform: 'web', - defaultSubscription: 'type = "track"', - fields: { - user_id: user_id, - currency: currency, - value: value, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'generate_lead', { - currency: payload.currency, - value: payload.value, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/generated-types.ts deleted file mode 100644 index 3582face62..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/generated-types.ts +++ /dev/null @@ -1,68 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * The measurement ID associated with the web stream. Found in the Google Analytics UI under: Admin > Data Streams > Web > Measurement ID. - */ - measurementID: string - /** - * Set to false to disable all advertising features. Set to true by default. - */ - allowGoogleSignals?: boolean - /** - * Set to false to disable all advertising features. Set to true by default. - */ - allowAdPersonalizationSignals?: boolean - /** - * Specifies the domain used to store the analytics cookie. Set to “auto” by default. - */ - cookieDomain?: string - /** - * Every time a hit is sent to GA4, the analytics cookie expiration time is updated to be the current time plus the value of this field. The default value is two years (63072000 seconds). Please input the expiration value in seconds. More information in [Google Documentation](https://developers.google.com/analytics/devguides/collection/ga4/reference/config#) - */ - cookieExpirationInSeconds?: number - /** - * Appends additional flags to the analytics cookie. See [write a new cookie](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#write_a_new_cookie) for some examples of flags to set. - */ - cookieFlags?: string[] - /** - * Specifies the subpath used to store the analytics cookie. We recommend to add a forward slash, / , in the first field as it is the Default Value for GA4. - */ - cookiePath?: string - /** - * Specifies a prefix to prepend to the analytics cookie name. - */ - cookiePrefix?: string[] - /** - * Set to false to not update cookies on each page load. This has the effect of cookie expiration being relative to the first time a user visited. Set to true by default so update cookies on each page load. - */ - cookieUpdate?: boolean - /** - * Set to true to enable Google’s [Consent Mode](https://support.google.com/analytics/answer/9976101?hl=en). Set to false by default. - */ - enableConsentMode?: boolean - /** - * The default value for ad cookies consent state. This is only used if Enable Consent Mode is on. Set to “granted” if it is not explicitly set. Consent state can be updated for each user in the Set Configuration Fields action. - */ - defaultAdsStorageConsentState?: string - /** - * The default value for analytics cookies consent state. This is only used if Enable Consent Mode is on. Set to “granted” if it is not explicitly set. Consent state can be updated for each user in the Set Configuration Fields action. - */ - defaultAnalyticsStorageConsentState?: string - /** - * Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on. - */ - adUserDataConsentState?: string - /** - * Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on. - */ - adPersonalizationConsentState?: string - /** - * If your CMP loads asynchronously, it might not always run before the Google tag. To handle such situations, specify a millisecond value to control how long to wait before the consent state update is sent. Please input the wait_for_update in milliseconds. - */ - waitTimeToUpdateConsentStage?: number - /** - * Set to false to prevent the default snippet from sending page views. Enabled by default. - */ - pageView?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/index.ts deleted file mode 100644 index edc13ac595..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/index.ts +++ /dev/null @@ -1,264 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' - -import addPaymentInfo from './addPaymentInfo' -import addToCart from './addToCart' -import addToWishlist from './addToWishlist' -import beginCheckout from './beginCheckout' -import customEvent from './customEvent' -import login from './login' -import generateLead from './generateLead' -import purchase from './purchase' -import refund from './refund' -import removeFromCart from './removeFromCart' -import search from './search' -import selectItem from './selectItem' -import selectPromotion from './selectPromotion' -import signUp from './signUp' -import viewCart from './viewCart' -import viewItem from './viewItem' -import viewItemList from './viewItemList' -import viewPromotion from './viewPromotion' -import setConfigurationFields from './setConfigurationFields' -import { defaultValues, DestinationDefinition } from '@segment/actions-core' - -declare global { - interface Window { - gtag: Function - dataLayer: any - } -} - -type ConsentParamsArg = 'granted' | 'denied' | undefined - -const presets: DestinationDefinition['presets'] = [ - { - name: `Set Configuration Fields`, - subscribe: 'type = "page"', - partnerAction: 'setConfigurationFields', - mapping: defaultValues(setConfigurationFields.fields), - type: 'automatic' - } -] - -export const destination: BrowserDestinationDefinition = { - name: 'Google Analytics 4 Web', - slug: 'actions-google-analytics-4-web', - mode: 'device', - - settings: { - measurementID: { - description: - 'The measurement ID associated with the web stream. Found in the Google Analytics UI under: Admin > Data Streams > Web > Measurement ID.', - label: 'Measurement ID', - type: 'string', - required: true - }, - allowGoogleSignals: { - description: 'Set to false to disable all advertising features. Set to true by default.', - label: 'Allow Google Signals', - type: 'boolean', - default: true - }, - allowAdPersonalizationSignals: { - description: 'Set to false to disable all advertising features. Set to true by default.', - label: 'Allow Ad Personalization Signals', - type: 'boolean', - default: true - }, - cookieDomain: { - description: 'Specifies the domain used to store the analytics cookie. Set to “auto” by default.', - label: 'Cookie Domain', - type: 'string', - default: 'auto' - }, - cookieExpirationInSeconds: { - description: `Every time a hit is sent to GA4, the analytics cookie expiration time is updated to be the current time plus the value of this field. The default value is two years (63072000 seconds). Please input the expiration value in seconds. More information in [Google Documentation](https://developers.google.com/analytics/devguides/collection/ga4/reference/config#)`, - label: 'Cookie Expiration In Seconds', - type: 'number', - default: 63072000 - }, - cookieFlags: { - description: `Appends additional flags to the analytics cookie. See [write a new cookie](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#write_a_new_cookie) for some examples of flags to set.`, - label: 'Cookie Flag', - type: 'string', - default: undefined, - multiple: true - }, - cookiePath: { - description: `Specifies the subpath used to store the analytics cookie. We recommend to add a forward slash, / , in the first field as it is the Default Value for GA4.`, - label: 'Cookie Path', - type: 'string', - default: '/' - }, - cookiePrefix: { - description: `Specifies a prefix to prepend to the analytics cookie name.`, - label: 'Cookie Prefix', - type: 'string', - default: undefined, - multiple: true - }, - cookieUpdate: { - description: `Set to false to not update cookies on each page load. This has the effect of cookie expiration being relative to the first time a user visited. Set to true by default so update cookies on each page load.`, - label: 'Cookie Update', - type: 'boolean', - default: true - }, - enableConsentMode: { - description: `Set to true to enable Google’s [Consent Mode](https://support.google.com/analytics/answer/9976101?hl=en). Set to false by default.`, - label: 'Enable Consent Mode', - type: 'boolean', - default: false - }, - defaultAdsStorageConsentState: { - description: - 'The default value for ad cookies consent state. This is only used if Enable Consent Mode is on. Set to “granted” if it is not explicitly set. Consent state can be updated for each user in the Set Configuration Fields action.', - label: 'Default Ads Storage Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: 'granted', - depends_on: { - conditions: [ - { - fieldKey: 'enableConsentMode', - operator: 'is', - value: true - } - ] - } - }, - defaultAnalyticsStorageConsentState: { - description: - 'The default value for analytics cookies consent state. This is only used if Enable Consent Mode is on. Set to “granted” if it is not explicitly set. Consent state can be updated for each user in the Set Configuration Fields action.', - label: 'Default Analytics Storage Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: 'granted', - depends_on: { - conditions: [ - { - fieldKey: 'enableConsentMode', - operator: 'is', - value: true - } - ] - } - }, - adUserDataConsentState: { - description: - 'Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on.', - label: 'Ad User Data Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: undefined, - depends_on: { - conditions: [ - { - fieldKey: 'enableConsentMode', - operator: 'is', - value: true - } - ] - } - }, - adPersonalizationConsentState: { - description: - 'Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on.', - label: 'Ad Personalization Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: undefined, - depends_on: { - conditions: [ - { - fieldKey: 'enableConsentMode', - operator: 'is', - value: true - } - ] - } - }, - waitTimeToUpdateConsentStage: { - description: - 'If your CMP loads asynchronously, it might not always run before the Google tag. To handle such situations, specify a millisecond value to control how long to wait before the consent state update is sent. Please input the wait_for_update in milliseconds.', - label: 'Wait Time to Update Consent State', - type: 'number' - }, - pageView: { - description: 'Set to false to prevent the default snippet from sending page views. Enabled by default.', - label: 'Page Views', - type: 'boolean', - default: true - } - }, - - initialize: async ({ settings }, deps) => { - window.dataLayer = window.dataLayer || [] - window.gtag = function () { - // eslint-disable-next-line prefer-rest-params - window.dataLayer.push(arguments) - } - - window.gtag('js', new Date()) - if (settings.enableConsentMode) { - const consent: { - ad_storage: ConsentParamsArg - analytics_storage: ConsentParamsArg - wait_for_update: number | undefined - ad_user_data?: ConsentParamsArg - ad_personalization?: ConsentParamsArg - } = { - ad_storage: settings.defaultAdsStorageConsentState as ConsentParamsArg, - analytics_storage: settings.defaultAnalyticsStorageConsentState as ConsentParamsArg, - wait_for_update: settings.waitTimeToUpdateConsentStage - } - if (settings.adUserDataConsentState) { - consent.ad_user_data = settings.adUserDataConsentState as ConsentParamsArg - } - if (settings.adPersonalizationConsentState) { - consent.ad_personalization = settings.adPersonalizationConsentState as ConsentParamsArg - } - gtag('consent', 'default', consent) - } - const script = `https://www.googletagmanager.com/gtag/js?id=${settings.measurementID}` - await deps.loadScript(script) - return window.gtag - }, - presets, - actions: { - addPaymentInfo, - login, - signUp, - search, - addToCart, - addToWishlist, - removeFromCart, - selectItem, - selectPromotion, - viewItem, - viewPromotion, - beginCheckout, - purchase, - refund, - viewCart, - viewItemList, - generateLead, - customEvent, - setConfigurationFields - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/login/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/login/generated-types.ts deleted file mode 100644 index e1e758672f..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/login/generated-types.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * The method used to login. - */ - method?: string - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/login/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/login/index.ts deleted file mode 100644 index 122cae19eb..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/login/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { user_properties, params, user_id, method, send_to } from '../ga4-properties' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Login', - description: 'Send event when a user logs in', - platform: 'web', - defaultSubscription: 'type = "track" and event = "Signed In"', - fields: { - user_id: user_id, - method: method, - user_properties: user_properties, - params: params, - send_to: send_to - }, - - perform: (gtag, { payload, settings }) => { - gtag('event', 'login', { - method: payload.method, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/purchase/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/purchase/generated-types.ts deleted file mode 100644 index 59e0cd9074..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/purchase/generated-types.ts +++ /dev/null @@ -1,130 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency: string - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The unique identifier of a transaction. - */ - transaction_id: string - /** - * Shipping cost associated with the transaction. - */ - shipping?: number - /** - * Total tax associated with the transaction. - */ - tax?: number - /** - * The monetary value of the event. - */ - value?: number - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/purchase/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/purchase/index.ts deleted file mode 100644 index 09a5ef4017..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/purchase/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { - coupon, - currency, - transaction_id, - value, - user_id, - shipping, - tax, - items_multi_products, - params, - user_properties, - send_to -} from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'Purchase', - description: 'This event signifies when one or more items is purchased by a user.', - defaultSubscription: 'type = "track" and event = "Order Completed"', - platform: 'web', - fields: { - user_id: user_id, - coupon: { ...coupon, default: { '@path': '$.properties.coupon' } }, - currency: { ...currency, required: true }, - items: { - ...items_multi_products, - required: true - }, - transaction_id: { ...transaction_id, required: true }, - shipping: shipping, - tax: tax, - value: { ...value, default: { '@path': '$.properties.total' } }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'purchase', { - currency: payload.currency, - transaction_id: payload.transaction_id, - value: payload.value, - coupon: payload.coupon, - tax: payload.tax, - shipping: payload.shipping, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/refund/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/refund/generated-types.ts deleted file mode 100644 index e2a9e691e2..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/refund/generated-types.ts +++ /dev/null @@ -1,134 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * The unique identifier of a transaction. - */ - transaction_id: string - /** - * The monetary value of the event. - */ - value?: number - /** - * Store or affiliation from which this transaction occurred (e.g. Google Store). - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Shipping cost associated with the transaction. - */ - shipping?: number - /** - * Total tax associated with the transaction. - */ - tax?: number - /** - * The list of products purchased. - */ - items?: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/refund/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/refund/index.ts deleted file mode 100644 index bfc5f0386b..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/refund/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { - coupon, - transaction_id, - user_id, - currency, - value, - affiliation, - shipping, - items_multi_products, - params, - user_properties, - tax, - send_to -} from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'Refund', - description: 'This event signifies when one or more items is refunded to a user.', - defaultSubscription: 'type = "track" and event = "Order Refunded"', - platform: 'web', - fields: { - user_id: user_id, - currency: currency, - transaction_id: { ...transaction_id, required: true }, - value: { ...value, default: { '@path': '$.properties.total' } }, - affiliation: affiliation, - coupon: coupon, - shipping: shipping, - tax: tax, - items: { - ...items_multi_products - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'refund', { - currency: payload.currency, - transaction_id: payload.transaction_id, // Transaction ID. Required for purchases and refunds. - value: payload.value, - affiliation: payload.affiliation, - coupon: payload.coupon, - shipping: payload.shipping, - tax: payload.tax, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/removeFromCart/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/removeFromCart/generated-types.ts deleted file mode 100644 index b6d8985b27..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/removeFromCart/generated-types.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * The monetary value of the event. - */ - value?: number - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/removeFromCart/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/removeFromCart/index.ts deleted file mode 100644 index b72832ff69..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/removeFromCart/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { user_properties, params, value, user_id, currency, items_single_products, send_to } from '../ga4-properties' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Remove from Cart', - description: 'This event signifies that an item was removed from a cart.', - platform: 'web', - defaultSubscription: 'type = "track" and event = "Product Removed"', - fields: { - user_id: user_id, - currency: currency, - value: value, - items: { - ...items_single_products, - required: true - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'remove_from_cart', { - currency: payload.currency, - value: payload.value, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/search/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/search/generated-types.ts deleted file mode 100644 index 686241fd58..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/search/generated-types.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * The term that was searched for. - */ - search_term?: string - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/search/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/search/index.ts deleted file mode 100644 index 9a4ca89a71..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/search/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { user_properties, params, user_id, search_term, send_to } from '../ga4-properties' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Search', - description: 'The term that was searched for.', - defaultSubscription: 'type = "track" and event = "Products Searched"', - platform: 'web', - fields: { - user_id: user_id, - user_properties: user_properties, - params: params, - search_term: search_term, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'search', { - search_term: payload.search_term, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/selectItem/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/selectItem/generated-types.ts deleted file mode 100644 index 70b44615db..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/selectItem/generated-types.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/selectItem/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/selectItem/index.ts deleted file mode 100644 index a64c762435..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/selectItem/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { - user_properties, - params, - user_id, - items_single_products, - item_list_name, - item_list_id, - send_to -} from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'Select Item', - description: 'This event signifies an item was selected from a list.', - defaultSubscription: 'type = "track" and event = "Product Clicked"', - platform: 'web', - fields: { - user_id: user_id, - item_list_name: item_list_name, - item_list_id: item_list_id, - items: { - ...items_single_products, - required: true - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'select_item', { - item_list_id: payload.item_list_id, - item_list_name: payload.item_list_name, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/selectPromotion/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/selectPromotion/generated-types.ts deleted file mode 100644 index 91725ada01..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/selectPromotion/generated-types.ts +++ /dev/null @@ -1,142 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * The name of the promotional creative. - */ - creative_name?: string - /** - * The name of the promotional creative slot associated with the event. - */ - creative_slot?: string - /** - * The ID of the location. - */ - location_id?: string - /** - * The ID of the promotion associated with the event. - */ - promotion_id?: string - /** - * The name of the promotion associated with the event. - */ - promotion_name?: string - /** - * The list of products purchased. - */ - items?: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - /** - * The name of the promotional creative. - */ - creative_name?: string - /** - * The name of the promotional creative slot associated with the event. - */ - creative_slot?: string - /** - * The name of the promotion associated with the event. - */ - promotion_name?: string - /** - * The ID of the promotion associated with the event. - */ - promotion_id?: string - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/selectPromotion/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/selectPromotion/index.ts deleted file mode 100644 index 28eee4036f..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/selectPromotion/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { - creative_name, - user_id, - creative_slot, - promotion_id, - promotion_name, - minimal_items, - items_single_products, - params, - user_properties, - location_id, - send_to -} from '../ga4-properties' -const action: BrowserActionDefinition = { - title: 'Select Promotion', - description: 'This event signifies a promotion was selected from a list.', - defaultSubscription: 'type = "track" and event = "Promotion Clicked"', - platform: 'web', - fields: { - user_id: user_id, - creative_name: creative_name, - creative_slot: { ...creative_slot, default: { '@path': '$.properties.creative' } }, - location_id: location_id, - promotion_id: { ...promotion_id, default: { '@path': '$.properties.promotion_id' } }, - promotion_name: { ...promotion_name, default: { '@path': '$.properties.name' } }, - items: { - ...items_single_products, - properties: { - ...minimal_items.properties, - creative_name: { - ...creative_name - }, - creative_slot: { - ...creative_slot - }, - promotion_name: { - ...promotion_name - }, - promotion_id: { - ...promotion_id - } - } - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'select_promotion', { - creative_name: payload.creative_name, - creative_slot: payload.creative_slot, - location_id: payload.location_id, - promotion_id: payload.promotion_id, - promotion_name: payload.promotion_name, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/setConfigurationFields/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/setConfigurationFields/generated-types.ts deleted file mode 100644 index 36d3f9f0a0..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/setConfigurationFields/generated-types.ts +++ /dev/null @@ -1,88 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * Consent state indicated by the user for ad cookies. Value must be “granted” or “denied.” This is only used if the Enable Consent Mode setting is on. - */ - ads_storage_consent_state?: string - /** - * Consent state indicated by the user for ad cookies. Value must be “granted” or “denied.” This is only used if the Enable Consent Mode setting is on. - */ - analytics_storage_consent_state?: string - /** - * Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on. - */ - ad_user_data_consent_state?: string - /** - * Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on. - */ - ad_personalization_consent_state?: string - /** - * Use campaign content to differentiate ads or links that point to the same URL. Setting this value will override the utm_content query parameter. - */ - campaign_content?: string - /** - * Use campaign ID to identify a specific campaign. Setting this value will override the utm_id query parameter. - */ - campaign_id?: string - /** - * Use campaign medium to identify a medium such as email or cost-per-click. Setting this value will override the utm_medium query parameter. - */ - campaign_medium?: string - /** - * Use campaign name to identify a specific product promotion or strategic campaign. Setting this value will override the utm_name query parameter. - */ - campaign_name?: string - /** - * Use campaign source to identify a search engine, newsletter name, or other source. Setting this value will override the utm_source query parameter. - */ - campaign_source?: string - /** - * Use campaign term to note the keywords for this ad. Setting this value will override the utm_term query parameter. - */ - campaign_term?: string - /** - * Categorize pages and screens into custom buckets so you can see metrics for related groups of information. More information in [Google documentation](https://support.google.com/analytics/answer/11523339). - */ - content_group?: string - /** - * The language preference of the user. If not set, defaults to the user's navigator.language value. - */ - language?: string - /** - * The full URL of the page. If not set, defaults to the user's document.location value. - */ - page_location?: string - /** - * The referral source that brought traffic to a page. This value is also used to compute the traffic source. The format of this value is a URL. If not set, defaults to the user's document.referrer value. - */ - page_referrer?: string - /** - * The title of the page or document. If not set, defaults to the user's document.title value. - */ - page_title?: string - /** - * The resolution of the screen. Format should be two positive integers separated by an x (i.e. 800x600). If not set, calculated from the user's window.screen value. - */ - screen_resolution?: string - /** - * Selection overrides toggled value set within Settings - */ - send_page_view?: boolean - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/setConfigurationFields/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/setConfigurationFields/index.ts deleted file mode 100644 index bfc4451ceb..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/setConfigurationFields/index.ts +++ /dev/null @@ -1,234 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { user_id, user_properties, params } from '../ga4-properties' -type ConsentParamsArg = 'granted' | 'denied' | undefined - -const defaultCookieExpiryInSecond = 63072000 -const defaultCookieDomain = 'auto' -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Set Configuration Fields', - description: 'Set custom values for the GA4 configuration fields.', - platform: 'web', - defaultSubscription: 'type = "page"', - lifecycleHook: 'before', - fields: { - user_id: user_id, - user_properties: user_properties, - ads_storage_consent_state: { - description: - 'Consent state indicated by the user for ad cookies. Value must be “granted” or “denied.” This is only used if the Enable Consent Mode setting is on.', - label: 'Ads Storage Consent State', - type: 'string' - }, - analytics_storage_consent_state: { - description: - 'Consent state indicated by the user for ad cookies. Value must be “granted” or “denied.” This is only used if the Enable Consent Mode setting is on.', - label: 'Analytics Storage Consent State', - type: 'string' - }, - ad_user_data_consent_state: { - description: - 'Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on.', - label: 'Ad User Data Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: undefined - }, - ad_personalization_consent_state: { - description: - 'Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on.', - label: 'Ad Personalization Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: undefined - }, - campaign_content: { - description: - 'Use campaign content to differentiate ads or links that point to the same URL. Setting this value will override the utm_content query parameter.', - label: 'Campaign Content', - type: 'string' - }, - campaign_id: { - description: - 'Use campaign ID to identify a specific campaign. Setting this value will override the utm_id query parameter. ', - label: 'Campaign ID', - type: 'string' - }, - campaign_medium: { - description: - 'Use campaign medium to identify a medium such as email or cost-per-click. Setting this value will override the utm_medium query parameter.', - label: 'Campaign Medium', - type: 'string' - }, - campaign_name: { - description: - 'Use campaign name to identify a specific product promotion or strategic campaign. Setting this value will override the utm_name query parameter.', - label: 'Campaign Name', - type: 'string' - }, - campaign_source: { - description: - 'Use campaign source to identify a search engine, newsletter name, or other source. Setting this value will override the utm_source query parameter.', - label: 'Campaign Source', - type: 'string' - }, - campaign_term: { - description: - 'Use campaign term to note the keywords for this ad. Setting this value will override the utm_term query parameter.', - label: 'Campaign Term', - type: 'string' - }, - content_group: { - description: `Categorize pages and screens into custom buckets so you can see metrics for related groups of information. More information in [Google documentation](https://support.google.com/analytics/answer/11523339).`, - label: 'Content Group', - type: 'string' - }, - language: { - description: `The language preference of the user. If not set, defaults to the user's navigator.language value.`, - label: 'Language', - type: 'string' - }, - page_location: { - description: `The full URL of the page. If not set, defaults to the user's document.location value.`, - label: 'Page Location', - type: 'string' - }, - page_referrer: { - description: `The referral source that brought traffic to a page. This value is also used to compute the traffic source. The format of this value is a URL. If not set, defaults to the user's document.referrer value.`, - label: 'Page Referrer', - type: 'string' - }, - page_title: { - description: `The title of the page or document. If not set, defaults to the user's document.title value.`, - label: 'Page Title', - type: 'string' - }, - screen_resolution: { - description: `The resolution of the screen. Format should be two positive integers separated by an x (i.e. 800x600). If not set, calculated from the user's window.screen value.`, - label: 'Screen Resolution', - type: 'string' - }, - send_page_view: { - description: 'Selection overrides toggled value set within Settings', - label: 'Send Page Views', - type: 'boolean', - choices: [ - { label: 'True', value: 'true' }, - { label: 'False', value: 'false' } - ], - default: true - }, - params: params - }, - perform: (gtag, { payload, settings }) => { - const checkCookiePathDefaultValue = - settings.cookiePath != undefined && settings.cookiePath?.length !== 1 && settings.cookiePath !== '/' - - if (settings.enableConsentMode) { - const consentParams: { - ad_storage?: ConsentParamsArg - analytics_storage?: ConsentParamsArg - ad_user_data?: ConsentParamsArg - ad_personalization?: ConsentParamsArg - } = {} - if (payload.ads_storage_consent_state) { - consentParams.ad_storage = payload.ads_storage_consent_state as ConsentParamsArg - } - if (payload.analytics_storage_consent_state) { - consentParams.analytics_storage = payload.analytics_storage_consent_state as ConsentParamsArg - } - if (payload.ad_user_data_consent_state) { - consentParams.ad_user_data = payload.ad_user_data_consent_state as ConsentParamsArg - } - if (payload.ad_personalization_consent_state) { - consentParams.ad_personalization = payload.ad_personalization_consent_state as ConsentParamsArg - } - gtag('consent', 'update', consentParams) - } - type ConfigType = { [key: string]: unknown } - - const config: ConfigType = { - allow_ad_personalization_signals: settings.allowAdPersonalizationSignals, - allow_google_signals: settings.allowGoogleSignals, - ...payload.params - } - - if (settings.cookieUpdate != true) { - config.cookie_update = false - } - if (settings.cookieDomain != defaultCookieDomain) { - config.cookie_domain = settings.cookieDomain - } - if (settings.cookiePrefix) { - config.cookie_prefix = settings.cookiePrefix - } - if (settings.cookieExpirationInSeconds != defaultCookieExpiryInSecond) { - config.cookie_expires = settings.cookieExpirationInSeconds - } - if (checkCookiePathDefaultValue) { - config.cookie_path = settings.cookiePath - } - - if (payload.send_page_view != true || settings.pageView != true) { - config.send_page_view = payload.send_page_view ?? settings.pageView ?? true - } - if (settings.cookieFlags) { - config.cookie_flags = settings.cookieFlags - } - - if (payload.screen_resolution) { - config.screen_resolution = payload.screen_resolution - } - if (payload.user_id) { - config.user_id = payload.user_id - } - if (payload.user_properties) { - config.user_properties = payload.user_properties - } - if (payload.page_title) { - config.page_title = payload.page_title - } - if (payload.page_referrer) { - config.page_referrer = payload.page_referrer - } - if (payload.page_location) { - config.page_location = payload.page_location - } - if (payload.language) { - config.language = payload.language - } - if (payload.content_group) { - config.content_group = payload.content_group - } - if (payload.campaign_term) { - config.campaign_term = payload.campaign_term - } - if (payload.campaign_source) { - config.campaign_source = payload.campaign_source - } - if (payload.campaign_name) { - config.campaign_name = payload.campaign_name - } - if (payload.campaign_medium) { - config.campaign_medium = payload.campaign_medium - } - if (payload.campaign_id) { - config.campaign_id = payload.campaign_id - } - if (payload.campaign_content) { - config.campaign_content = payload.campaign_content - } - - gtag('config', settings.measurementID, config) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/signUp/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/signUp/generated-types.ts deleted file mode 100644 index e1e758672f..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/signUp/generated-types.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * The method used to login. - */ - method?: string - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/signUp/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/signUp/index.ts deleted file mode 100644 index 6e777976b0..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/signUp/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { user_properties, params, user_id, method, send_to } from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'Sign Up', - description: 'The method used for sign up.', - defaultSubscription: 'type = "track" and event = "Signed Up"', - platform: 'web', - fields: { - user_id: user_id, - method: method, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'sign_up', { - method: payload.method, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewCart/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/viewCart/generated-types.ts deleted file mode 100644 index b6d8985b27..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewCart/generated-types.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * The monetary value of the event. - */ - value?: number - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewCart/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/viewCart/index.ts deleted file mode 100644 index 63c366cf30..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewCart/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { user_properties, params, currency, value, user_id, items_multi_products, send_to } from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'View Cart', - description: 'This event signifies that a user viewed their cart.', - defaultSubscription: 'type = "track" and event = "Cart Viewed"', - platform: 'web', - fields: { - user_id: user_id, - currency: currency, - value: value, - items: { - ...items_multi_products, - required: true - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'view_cart', { - currency: payload.currency, - value: payload.value, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItem/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItem/generated-types.ts deleted file mode 100644 index b6d8985b27..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItem/generated-types.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * Currency of the items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * The monetary value of the event. - */ - value?: number - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItem/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItem/index.ts deleted file mode 100644 index 1a23e19801..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItem/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { user_properties, params, currency, user_id, value, items_single_products, send_to } from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'View Item', - description: - 'This event signifies that some content was shown to the user. Use this event to discover the most popular items viewed.', - defaultSubscription: 'type = "track" and event = "Product Viewed"', - platform: 'web', - fields: { - user_id: user_id, - currency: currency, - value: value, - items: { - ...items_single_products, - required: true - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'view_item', { - currency: payload.currency, - value: payload.value, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItemList/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItemList/generated-types.ts deleted file mode 100644 index c92981ba95..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItemList/generated-types.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItemList/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItemList/index.ts deleted file mode 100644 index 4e994d5110..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewItemList/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -import { - user_properties, - params, - user_id, - items_multi_products, - item_list_name, - item_list_id, - send_to -} from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'View Item List', - description: 'Log this event when the user has been presented with a list of items of a certain category.', - platform: 'web', - defaultSubscription: 'type = "track" and event = "Product List Viewed"', - fields: { - user_id: user_id, - item_list_id: item_list_id, - item_list_name: item_list_name, - items: { - ...items_multi_products, - required: true - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'view_item_list', { - item_list_id: payload.item_list_id, - item_list_name: payload.item_list_name, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewPromotion/generated-types.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/viewPromotion/generated-types.ts deleted file mode 100644 index 826cba82d2..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewPromotion/generated-types.ts +++ /dev/null @@ -1,142 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for a user. See Google's [User-ID for cross-platform analysis](https://support.google.com/analytics/answer/9213390) and [Reporting: deduplicate user counts](https://support.google.com/analytics/answer/9355949?hl=en) documentation for more information on this identifier. - */ - user_id?: string - /** - * The name of the promotional creative. - */ - creative_name?: string - /** - * The name of the promotional creative slot associated with the event. - */ - creative_slot?: string - /** - * The ID of the location. - */ - location_id?: string - /** - * The ID of the promotion associated with the event. - */ - promotion_id?: string - /** - * The name of the promotion associated with the event. - */ - promotion_name?: string - /** - * The list of products purchased. - */ - items: { - /** - * Identifier for the product being purchased. - */ - item_id?: string - /** - * Name of the product being purchased. - */ - item_name?: string - /** - * A product affiliation to designate a supplying company or brick and mortar store location. - */ - affiliation?: string - /** - * Coupon code used for a purchase. - */ - coupon?: string - /** - * Currency of the purchase or items associated with the event, in 3-letter ISO 4217 format. - */ - currency?: string - /** - * Monetary value of discount associated with a purchase. - */ - discount?: number - /** - * The index/position of the item in a list. - */ - index?: number - /** - * Brand associated with the product. - */ - item_brand?: string - /** - * Product category. - */ - item_category?: string - /** - * Product category 2. - */ - item_category2?: string - /** - * Product category 3. - */ - item_category3?: string - /** - * Product category 4. - */ - item_category4?: string - /** - * Product category 5. - */ - item_category5?: string - /** - * The ID of the list in which the item was presented to the user. - */ - item_list_id?: string - /** - * The name of the list in which the item was presented to the user. - */ - item_list_name?: string - /** - * Variant of the product (e.g. Black). - */ - item_variant?: string - /** - * The location associated with the item. - */ - location_id?: string - /** - * Price of the product being purchased, in units of the specified currency parameter. - */ - price?: number - /** - * Item quantity. - */ - quantity?: number - /** - * The name of the promotional creative. - */ - creative_name?: string - /** - * The name of the promotional creative slot associated with the event. - */ - creative_slot?: string - /** - * The name of the promotion associated with the event. - */ - promotion_name?: string - /** - * The ID of the promotion associated with the event. - */ - promotion_id?: string - [k: string]: unknown - }[] - /** - * The user properties to send to Google Analytics 4. You must create user-scoped dimensions to ensure custom properties are picked up by Google. See Google’s [Custom user properties](https://support.google.com/analytics/answer/9269570) to learn how to set and register user properties. - */ - user_properties?: { - [k: string]: unknown - } - /** - * The event parameters to send to Google Analytics 4. - */ - params?: { - [k: string]: unknown - } - /** - * If the send_to parameter is not set, events are routed to all Tag Ids (AW-xxx, G-xxx) set via Google Tag - */ - send_to?: boolean -} diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewPromotion/index.ts b/packages/browser-destinations/destinations/google-analytics-4-web/src/viewPromotion/index.ts deleted file mode 100644 index 539d564fd5..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/src/viewPromotion/index.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { - creative_name, - creative_slot, - promotion_id, - promotion_name, - user_id, - minimal_items, - items_single_products, - params, - user_properties, - location_id, - send_to -} from '../ga4-properties' - -const action: BrowserActionDefinition = { - title: 'View Promotion', - description: 'This event signifies a promotion was viewed from a list.', - defaultSubscription: 'type = "track" and event = "Promotion Viewed"', - platform: 'web', - fields: { - user_id: user_id, - creative_name: creative_name, - creative_slot: { ...creative_slot, default: { '@path': '$.properties.creative' } }, - location_id: location_id, - promotion_id: { ...promotion_id, default: { '@path': '$.properties.promotion_id' } }, - promotion_name: { ...promotion_name, default: { '@path': '$.properties.name' } }, - items: { - ...items_single_products, - required: true, - properties: { - ...minimal_items.properties, - creative_name: { - ...creative_name - }, - creative_slot: { - ...creative_slot - }, - promotion_name: { - ...promotion_name - }, - promotion_id: { - ...promotion_id - } - } - }, - user_properties: user_properties, - params: params, - send_to: send_to - }, - perform: (gtag, { payload, settings }) => { - gtag('event', 'view_promotion', { - creative_name: payload.creative_name, - creative_slot: payload.creative_slot, - location_id: payload.location_id, - promotion_id: payload.promotion_id, - promotion_name: payload.promotion_name, - items: payload.items, - user_id: payload.user_id ?? undefined, - user_properties: payload.user_properties, - send_to: payload.send_to == true ? settings.measurementID : 'default', - ...payload.params - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-analytics-4-web/tsconfig.json b/packages/browser-destinations/destinations/google-analytics-4-web/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/google-analytics-4-web/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/google-campaign-manager/README.md b/packages/browser-destinations/destinations/google-campaign-manager/README.md deleted file mode 100644 index b6cd3877f9..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# @segment/analytics-browser-actions-google-campaign-manager - -The Google Campaign Manager browser action destination for use with @segment/analytics-next. - -## License - -MIT License - -Copyright (c) 2024 Segment - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -## Contributing - -All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. diff --git a/packages/browser-destinations/destinations/google-campaign-manager/package.json b/packages/browser-destinations/destinations/google-campaign-manager/package.json deleted file mode 100644 index 179019d1df..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-google-campaign-manager", - "version": "1.38.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/google-campaign-manager/src/__tests__/counterActivity.test.ts b/packages/browser-destinations/destinations/google-campaign-manager/src/__tests__/counterActivity.test.ts deleted file mode 100644 index 22ed58bf91..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/src/__tests__/counterActivity.test.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleCampaignManager, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'counterActivity', - name: 'Counter Activity', - enabled: true, - subscribe: 'type = "track"', - mapping: { - activityGroupTagString: { - '@path': '$.properties.activityGroupTagString' - }, - activityTagString: { - '@path': '$.properties.activityTagString' - }, - countingMethod: { - '@path': '$.properties.countingMethod' - }, - enableDynamicTags: { - '@path': '$.properties.enableDynamicTags' - }, - sessionId: { - '@path': '$.properties.sessionId' - }, - uVariables: { - u1: 'custom variable 1', - u2: 'custom variable 2' - }, - dcCustomParams: { - dc_lat: 0, - tag_for_child_directed_treatment: 1 - } - } - } -] - -describe('GoogleCampaignManager.counterActivity', () => { - const settings = { - advertiserId: 'test123', - allowAdPersonalizationSignals: false, - conversionLinker: false - } - - let mockGTAG: typeof gtag - let counterActivityEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleCampaignManager({ - ...settings, - subscriptions - }) - counterActivityEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGTAG = jest.fn() - - return Promise.resolve(mockGTAG) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('track event', async () => { - const activityGroupTagString = 'group' - const activityTagString = 'activity' - const countingMethod = 'standard' - const enableDynamicTags = false - - const context = new Context({ - event: 'Counter Activity', - type: 'track', - properties: { - activityGroupTagString, - activityTagString, - countingMethod, - enableDynamicTags - } - }) - await counterActivityEvent.track?.(context) - - expect(mockGTAG).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('conversion'), - expect.objectContaining({ - allow_custom_scripts: enableDynamicTags, - send_to: `${settings.advertiserId}/${activityGroupTagString}/${activityTagString}+${countingMethod}`, - u1: 'custom variable 1', - u2: 'custom variable 2', - dc_custom_params: { dc_lat: 0, tag_for_child_directed_treatment: 1 } - }) - ) - }) - - test('track event (per session)', async () => { - const activityGroupTagString = 'group' - const activityTagString = 'activity' - const countingMethod = 'per_session' - const enableDynamicTags = false - const sessionId = 'my_session' - - const context = new Context({ - event: 'Counter Activity', - type: 'track', - properties: { - activityGroupTagString, - activityTagString, - countingMethod, - enableDynamicTags, - sessionId - } - }) - await counterActivityEvent.track?.(context) - - expect(mockGTAG).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('conversion'), - expect.objectContaining({ - allow_custom_scripts: enableDynamicTags, - send_to: `${settings.advertiserId}/${activityGroupTagString}/${activityTagString}+${countingMethod}`, - session_id: sessionId, - u1: 'custom variable 1', - u2: 'custom variable 2', - dc_custom_params: { dc_lat: 0, tag_for_child_directed_treatment: 1 } - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-campaign-manager/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/google-campaign-manager/src/__tests__/index.test.ts deleted file mode 100644 index f8d817df1e..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/src/__tests__/index.test.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import googleCampaignManager, { destination } from '../index' -import { Analytics, Context } from '@segment/analytics-next' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'salesActivity', - name: 'Sales Activity', - enabled: true, - subscribe: 'type = "track"', - mapping: {} - } -] - -describe('Google Tag for Campaign Manager', () => { - const defaultSettings = { - advertiserId: 'test123', - allowAdPersonalizationSignals: false, - conversionLinker: false - } - beforeEach(async () => { - jest.restoreAllMocks() - - const [googleCampaignManagerPlugin] = await googleCampaignManager({ - ...defaultSettings, - subscriptions - }) - jest.spyOn(destination, 'initialize') - - await googleCampaignManagerPlugin.load(Context.system(), {} as Analytics) - }) - - it('should not update consent if enable_consent mode is denied', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: false - } - - const [event] = await googleCampaignManager({ ...settings, subscriptions }) - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.dataLayer).toEqual( - expect.arrayContaining([expect.not.objectContaining(Object.assign({}, ['consent', 'default', {}]))]) - ) - }) - - it('should update consent if analytics storage is granted', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: true, - defaultAnalyticsStorageConsentState: 'granted' - } - - const [event] = await googleCampaignManager({ ...settings, subscriptions }) - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.dataLayer).toEqual( - expect.arrayContaining([ - expect.objectContaining(Object.assign({}, ['consent', 'default', { analytics_storage: 'granted' }])) - ]) - ) - }) - - it('should update consent if analytics storage is denied', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: true, - defaultAnalyticsStorageConsentState: 'denied' - } - - const [event] = await googleCampaignManager({ ...settings, subscriptions }) - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.dataLayer).toEqual( - expect.arrayContaining([ - expect.objectContaining(Object.assign({}, ['consent', 'default', { analytics_storage: 'denied' }])) - ]) - ) - }) - it('should update consent if Ad storage is granted', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: true, - defaultAdsStorageConsentState: 'granted' - } - - const [event] = await googleCampaignManager({ ...settings, subscriptions }) - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.dataLayer).toEqual( - expect.arrayContaining([ - expect.objectContaining(Object.assign({}, ['consent', 'default', { ad_storage: 'granted' }])) - ]) - ) - }) - it('should update consent if Ad storage is denied', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: true, - defaultAdsStorageConsentState: 'denied' - } - - const [event] = await googleCampaignManager({ ...settings, subscriptions }) - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.dataLayer).toEqual( - expect.arrayContaining([ - expect.objectContaining(Object.assign({}, ['consent', 'default', { ad_storage: 'denied' }])) - ]) - ) - }) - it('should update consent if Ad user data is granted', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: true, - adUserDataConsentState: 'granted' - } - - const [event] = await googleCampaignManager({ ...settings, subscriptions }) - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.dataLayer).toEqual( - expect.arrayContaining([ - expect.objectContaining(Object.assign({}, ['consent', 'default', { ad_user_data: 'granted' }])) - ]) - ) - }) - it('should update consent if Ad user data is denied', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: true, - adUserDataConsentState: 'denied' - } - - const [event] = await googleCampaignManager({ ...settings, subscriptions }) - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.dataLayer).toEqual( - expect.arrayContaining([ - expect.objectContaining(Object.assign({}, ['consent', 'default', { ad_user_data: 'denied' }])) - ]) - ) - }) - it('should update consent if Ad personalization is granted', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: true, - adPersonalizationConsentState: 'granted' - } - - const [event] = await googleCampaignManager({ ...settings, subscriptions }) - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.dataLayer).toEqual( - expect.arrayContaining([ - expect.objectContaining(Object.assign({}, ['consent', 'default', { ad_personalization: 'granted' }])) - ]) - ) - }) - it('should update consent if Ad personalization is denied', async () => { - const settings = { - ...defaultSettings, - enableConsentMode: true, - adPersonalizationConsentState: 'denied' - } - - const [event] = await googleCampaignManager({ ...settings, subscriptions }) - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.dataLayer).toEqual( - expect.arrayContaining([ - expect.objectContaining(Object.assign({}, ['consent', 'default', { ad_personalization: 'denied' }])) - ]) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-campaign-manager/src/__tests__/salesActivity.test.ts b/packages/browser-destinations/destinations/google-campaign-manager/src/__tests__/salesActivity.test.ts deleted file mode 100644 index 7bf44b3d71..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/src/__tests__/salesActivity.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import googleCampaignManager, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'salesActivity', - name: 'Sales Activity', - enabled: true, - subscribe: 'type = "track"', - mapping: { - activityGroupTagString: { - '@path': '$.properties.activityGroupTagString' - }, - activityTagString: { - '@path': '$.properties.activityTagString' - }, - countingMethod: { - '@path': '$.properties.countingMethod' - }, - enableDynamicTags: { - '@path': '$.properties.enableDynamicTags' - }, - value: { - '@path': '$.properties.value' - }, - transactionId: { - '@path': '$.properties.transactionId' - }, - quantity: 1, - uVariables: { - u1: 'custom variable 1', - u2: 'custom variable 2' - }, - dcCustomParams: { - dc_lat: 0, - tag_for_child_directed_treatment: 1 - } - } - } -] - -describe('GoogleCampaignManager.salesActivity', () => { - const settings = { - advertiserId: 'test123', - allowAdPersonalizationSignals: false, - conversionLinker: false - } - - let mockGTAG: typeof gtag - let salesActivityEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await googleCampaignManager({ - ...settings, - subscriptions - }) - salesActivityEvent = trackEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockGTAG = jest.fn() - - return Promise.resolve(mockGTAG) - }) - await trackEventPlugin.load(Context.system(), {} as Analytics) - }) - - test('track event', async () => { - const activityGroupTagString = 'group' - const activityTagString = 'activity' - const countingMethod = 'transactions' - const enableDynamicTags = false - const transactionId = 'my-transaction' - - const context = new Context({ - event: 'Sales Activity', - type: 'track', - properties: { - activityGroupTagString, - activityTagString, - countingMethod, - enableDynamicTags, - value: 10, - transactionId - } - }) - await salesActivityEvent.track?.(context) - - expect(mockGTAG).toHaveBeenCalledWith( - expect.anything(), - expect.stringContaining('purchase'), - expect.objectContaining({ - allow_custom_scripts: enableDynamicTags, - send_to: `${settings.advertiserId}/${activityGroupTagString}/${activityTagString}+${countingMethod}`, - quantity: 1, - value: 10, - transaction_id: transactionId, - u1: 'custom variable 1', - u2: 'custom variable 2', - dc_custom_params: { dc_lat: 0, tag_for_child_directed_treatment: 1 } - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/google-campaign-manager/src/counterActivity/generated-types.ts b/packages/browser-destinations/destinations/google-campaign-manager/src/counterActivity/generated-types.ts deleted file mode 100644 index c779e2a178..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/src/counterActivity/generated-types.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * An identifier for the Floodlight activity group associated with this activity, which appears as a parameter in your tags. This value is case sensitive. - */ - activityGroupTagString: string - /** - * An identifier for your Floodlight activity, which appears as a parameter in your tags. This value is case sensitive. - */ - activityTagString: string - /** - * In Campaign Manager, go to Floodlight -> Configuration, under Tags, if **Dynamic** is selected, select **True**. - */ - enableDynamicTags?: boolean - /** - * Specifies how conversions will be counted for this Floodlight activity. - */ - countingMethod: string - /** - * Use this field to insert a unique session ID if you’re using counter tags with a per session counting methodology. The session ID tells Campaign Manager 360 to count only one event per session on your site. - */ - sessionId?: string - /** - * Custom Floodlight variables enable you to capture information beyond the basics (visits and revenue) that you can collect with standard parameters in your tags. - */ - uVariables?: { - [k: string]: unknown - } - /** - * You can insert custom data into event snippets with the dc_custom_params field. This field accepts any values you want to pass to Google Marketing Platform. - */ - dcCustomParams?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/google-campaign-manager/src/counterActivity/index.ts b/packages/browser-destinations/destinations/google-campaign-manager/src/counterActivity/index.ts deleted file mode 100644 index ac4a1dd93f..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/src/counterActivity/index.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -const action: BrowserActionDefinition = { - title: 'Counter Activity', - description: 'Record non-monetary conversion data such as unique users, conversions, and session length.', - defaultSubscription: 'type = "track"', - platform: 'web', - fields: { - activityGroupTagString: { - label: 'Activity Group Tag String', - description: - 'An identifier for the Floodlight activity group associated with this activity, which appears as a parameter in your tags. This value is case sensitive.', - type: 'string', - required: true - }, - activityTagString: { - label: 'Activity Tag String', - description: - 'An identifier for your Floodlight activity, which appears as a parameter in your tags. This value is case sensitive.', - type: 'string', - required: true - }, - enableDynamicTags: { - label: 'Enable Dynamic Tags', - type: 'boolean', - description: - 'In Campaign Manager, go to Floodlight -> Configuration, under Tags, if **Dynamic** is selected, select **True**.' - }, - countingMethod: { - label: 'Counting Method', - type: 'string', - description: 'Specifies how conversions will be counted for this Floodlight activity.', - choices: [ - { value: 'standard', label: 'Standard' }, - { value: 'unique', label: 'Unique' }, - { value: 'per_session', label: 'Per Session' } - ], - required: true - }, - sessionId: { - label: 'Session ID', - description: - 'Use this field to insert a unique session ID if you’re using counter tags with a per session counting methodology. The session ID tells Campaign Manager 360 to count only one event per session on your site.', - type: 'string' - }, - uVariables: { - label: 'U Variables', - description: - 'Custom Floodlight variables enable you to capture information beyond the basics (visits and revenue) that you can collect with standard parameters in your tags.', - type: 'object', - defaultObjectUI: 'keyvalue:only' - }, - dcCustomParams: { - label: 'Custom Parameters', - description: - 'You can insert custom data into event snippets with the dc_custom_params field. This field accepts any values you want to pass to Google Marketing Platform.', - type: 'object', - defaultObjectUI: 'keyvalue:only' - } - }, - perform: (gtag, { payload, settings }) => { - const requestBody = { - allow_custom_scripts: payload.enableDynamicTags, - send_to: `${settings.advertiserId}/${payload.activityGroupTagString}/${payload.activityTagString}+${payload.countingMethod}`, - ...(payload.sessionId !== undefined && - payload.countingMethod == 'per_session' && { session_id: payload.sessionId }), - ...payload.uVariables, - ...(payload.dcCustomParams !== undefined && { dc_custom_params: { ...payload.dcCustomParams } }) - } - gtag('event', 'conversion', requestBody) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-campaign-manager/src/generated-types.ts b/packages/browser-destinations/destinations/google-campaign-manager/src/generated-types.ts deleted file mode 100644 index 70ed9aac4a..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/src/generated-types.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * In Campaign Manager, go to Floodlight -> Configuration, and Advertiser ID is located under the Configuration heading. - */ - advertiserId: string - /** - * This feature can be disabled if you do not want the global site tag to allow personalized remarketing data for site users. - */ - allowAdPersonalizationSignals: boolean - /** - * This feature can be disabled if you do not want the global site tag to set first party cookies on your site domain. - */ - conversionLinker: boolean - /** - * Set to true to enable Google’s [Consent Mode](https://support.google.com/analytics/answer/9976101?hl=en). Set to false by default. - */ - enableConsentMode?: boolean - /** - * Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on. - */ - adUserDataConsentState?: string - /** - * Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on. - */ - adPersonalizationConsentState?: string - /** - * The default value for ad cookies consent state. This is only used if Enable Consent Mode is on. Set to “granted” if it is not explicitly set. Consent state can be updated for each user in the Set Configuration Fields action. - */ - defaultAdsStorageConsentState?: string - /** - * The default value for analytics cookies consent state. This is only used if Enable Consent Mode is on. Set to “granted” if it is not explicitly set. Consent state can be updated for each user in the Set Configuration Fields action. - */ - defaultAnalyticsStorageConsentState?: string -} diff --git a/packages/browser-destinations/destinations/google-campaign-manager/src/index.ts b/packages/browser-destinations/destinations/google-campaign-manager/src/index.ts deleted file mode 100644 index 46ec587ec9..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/src/index.ts +++ /dev/null @@ -1,180 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import counterActivity from './counterActivity' -import salesActivity from './salesActivity' - -declare global { - interface Window { - gtag: typeof gtag - dataLayer: any - } -} - -type ConsentParamsArg = 'granted' | 'denied' | undefined - -export const destination: BrowserDestinationDefinition = { - name: 'Google Tag for Campaign Manager', - slug: 'actions-google-campaign-manager', - mode: 'device', - - settings: { - advertiserId: { - description: - 'In Campaign Manager, go to Floodlight -> Configuration, and Advertiser ID is located under the Configuration heading.', - label: 'Advertiser ID', - type: 'string', - required: true, - default: 'DC-' - }, - allowAdPersonalizationSignals: { - description: - 'This feature can be disabled if you do not want the global site tag to allow personalized remarketing data for site users.', - label: 'Allow Ad Personalization Signals', - type: 'boolean', - required: true, - default: true - }, - conversionLinker: { - description: - 'This feature can be disabled if you do not want the global site tag to set first party cookies on your site domain.', - label: 'Conversion Linker', - type: 'boolean', - required: true, - default: true - }, - enableConsentMode: { - description: `Set to true to enable Google’s [Consent Mode](https://support.google.com/analytics/answer/9976101?hl=en). Set to false by default.`, - label: 'Enable Consent Mode', - type: 'boolean', - default: false - }, - adUserDataConsentState: { - description: - 'Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on.', - label: 'Ad User Data Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: undefined, - depends_on: { - conditions: [ - { - fieldKey: 'enableConsentMode', - operator: 'is', - value: true - } - ] - } - }, - adPersonalizationConsentState: { - description: - 'Consent state indicated by the user for ad cookies. Value must be "granted" or "denied." This is only used if the Enable Consent Mode setting is on.', - label: 'Ad Personalization Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: undefined, - depends_on: { - conditions: [ - { - fieldKey: 'enableConsentMode', - operator: 'is', - value: true - } - ] - } - }, - defaultAdsStorageConsentState: { - description: - 'The default value for ad cookies consent state. This is only used if Enable Consent Mode is on. Set to “granted” if it is not explicitly set. Consent state can be updated for each user in the Set Configuration Fields action.', - label: 'Default Ads Storage Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: undefined, - depends_on: { - conditions: [ - { - fieldKey: 'enableConsentMode', - operator: 'is', - value: true - } - ] - } - }, - defaultAnalyticsStorageConsentState: { - description: - 'The default value for analytics cookies consent state. This is only used if Enable Consent Mode is on. Set to “granted” if it is not explicitly set. Consent state can be updated for each user in the Set Configuration Fields action.', - label: 'Default Analytics Storage Consent State', - type: 'string', - choices: [ - { label: 'Granted', value: 'granted' }, - { label: 'Denied', value: 'denied' } - ], - default: undefined, - depends_on: { - conditions: [ - { - fieldKey: 'enableConsentMode', - operator: 'is', - value: true - } - ] - } - } - }, - - initialize: async ({ settings }, deps) => { - window.dataLayer = window.dataLayer || [] - window.gtag = function () { - // eslint-disable-next-line prefer-rest-params - window.dataLayer.push(arguments) - } - window.gtag('set', 'allow_ad_personalization_signals', settings.allowAdPersonalizationSignals) - window.gtag('js', new Date()) - window.gtag('config', settings.advertiserId, { - conversion_linker: settings.conversionLinker - }) - if (settings.enableConsentMode) { - const consent: { - ad_storage?: ConsentParamsArg - analytics_storage?: ConsentParamsArg - ad_user_data?: ConsentParamsArg - ad_personalization?: ConsentParamsArg - allow_ad_personalization_signals?: Boolean - } = {} - - if (settings.defaultAnalyticsStorageConsentState) { - consent.analytics_storage = settings.defaultAnalyticsStorageConsentState as ConsentParamsArg - } - if (settings.defaultAdsStorageConsentState) { - consent.ad_storage = settings.defaultAdsStorageConsentState as ConsentParamsArg - } - if (settings.adUserDataConsentState) { - consent.ad_user_data = settings.adUserDataConsentState as ConsentParamsArg - } - if (settings.adPersonalizationConsentState) { - consent.ad_personalization = settings.adPersonalizationConsentState as ConsentParamsArg - } - - window.gtag('consent', 'default', consent) - } - const script = `https://www.googletagmanager.com/gtag/js?id=${settings.advertiserId}` - await deps.loadScript(script) - return window.gtag - }, - - actions: { - counterActivity, - salesActivity - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/google-campaign-manager/src/salesActivity/generated-types.ts b/packages/browser-destinations/destinations/google-campaign-manager/src/salesActivity/generated-types.ts deleted file mode 100644 index bb435cc8af..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/src/salesActivity/generated-types.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * An identifier for the Floodlight activity group associated with this activity, which appears as a parameter in your tags. This value is case sensitive. - */ - activityGroupTagString: string - /** - * An identifier for your Floodlight activity, which appears as a parameter in your tags. This value is case sensitive. - */ - activityTagString: string - /** - * In Campaign Manager, go to Floodlight -> Configuration, under Tags, if **Dynamic** is selected, select **True**. - */ - enableDynamicTags?: boolean - /** - * Specifies how conversions will be counted for this Floodlight activity. - */ - countingMethod: string - /** - * Use this field to insert a unique numerical identifier for each transaction. Can be alphanumeric. - */ - transactionId: string - /** - * Use this field to pass the revenue generated by a transaction. Typically the purchase price and value does not include taxes or shipping. - */ - value: string - /** - * - * Use this field to pass the number of items sold during a transaction: - * - If you're counting each transaction as a single conversion, the value is 1. - * - If you're counting each item sold during a single transaction as a separate conversion, insert the number of items sold as part of each transaction as the value. - * - The value must be an integer greater than zero. - * - */ - quantity: number - /** - * Custom Floodlight variables enable you to capture information beyond the basics (visits and revenue) that you can collect with standard parameters in your tags. - */ - uVariables?: { - [k: string]: unknown - } - /** - * You can insert custom data into event snippets with the dc_custom_params field. This field accepts any values you want to pass to Google Marketing Platform. - */ - dcCustomParams?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/google-campaign-manager/src/salesActivity/index.ts b/packages/browser-destinations/destinations/google-campaign-manager/src/salesActivity/index.ts deleted file mode 100644 index 1f07bd8ad6..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/src/salesActivity/index.ts +++ /dev/null @@ -1,98 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -const action: BrowserActionDefinition = { - title: 'Sales Activity', - description: 'Record monetary data for conversions, such as cost and the number of items sold.', - defaultSubscription: 'type = "track"', - platform: 'web', - fields: { - activityGroupTagString: { - label: 'Activity Group Tag String', - description: - 'An identifier for the Floodlight activity group associated with this activity, which appears as a parameter in your tags. This value is case sensitive.', - type: 'string', - required: true - }, - activityTagString: { - label: 'Activity Tag String', - description: - 'An identifier for your Floodlight activity, which appears as a parameter in your tags. This value is case sensitive.', - type: 'string', - required: true - }, - enableDynamicTags: { - label: 'Enable Dynamic Tags', - type: 'boolean', - description: - 'In Campaign Manager, go to Floodlight -> Configuration, under Tags, if **Dynamic** is selected, select **True**.' - }, - countingMethod: { - label: 'Counting Method', - type: 'string', - description: 'Specifies how conversions will be counted for this Floodlight activity.', - choices: [ - { value: 'transactions', label: 'Transactions' }, - { value: 'items_sold', label: 'Items Sold' } - ], - required: true - }, - transactionId: { - label: 'Transaction ID', - description: 'Use this field to insert a unique numerical identifier for each transaction. Can be alphanumeric.', - type: 'string', - required: true, - default: { - '@path': '$.properties.order_id' - } - }, - value: { - label: 'Value', - description: - 'Use this field to pass the revenue generated by a transaction. Typically the purchase price and value does not include taxes or shipping.', - type: 'string', - required: true, - default: { '@path': '$.properties.total' } - }, - quantity: { - label: 'Quantity', - description: ` - Use this field to pass the number of items sold during a transaction: - - If you're counting each transaction as a single conversion, the value is 1. - - If you're counting each item sold during a single transaction as a separate conversion, insert the number of items sold as part of each transaction as the value. - - The value must be an integer greater than zero. - `, - type: 'integer', - required: true - }, - uVariables: { - label: 'U Variables', - description: - 'Custom Floodlight variables enable you to capture information beyond the basics (visits and revenue) that you can collect with standard parameters in your tags.', - type: 'object', - defaultObjectUI: 'keyvalue:only' - }, - dcCustomParams: { - label: 'Custom Parameters', - description: - 'You can insert custom data into event snippets with the dc_custom_params field. This field accepts any values you want to pass to Google Marketing Platform.', - type: 'object', - defaultObjectUI: 'keyvalue:only' - } - }, - perform: (gtag, { payload, settings }) => { - const requestBody = { - allow_custom_scripts: payload.enableDynamicTags, - send_to: `${settings.advertiserId}/${payload.activityGroupTagString}/${payload.activityTagString}+${payload.countingMethod}`, - value: payload.value, - transaction_id: payload.transactionId, - quantity: payload.quantity, - ...payload.uVariables, - ...(payload.dcCustomParams !== undefined && { dc_custom_params: { ...payload.dcCustomParams } }) - } - gtag('event', 'purchase', requestBody) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/google-campaign-manager/tsconfig.json b/packages/browser-destinations/destinations/google-campaign-manager/tsconfig.json deleted file mode 100644 index c2a7897afd..0000000000 --- a/packages/browser-destinations/destinations/google-campaign-manager/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} diff --git a/packages/browser-destinations/destinations/heap/package.json b/packages/browser-destinations/destinations/heap/package.json deleted file mode 100644 index 2585ae7553..0000000000 --- a/packages/browser-destinations/destinations/heap/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-heap", - "version": "1.47.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/actions-core": "^3.116.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/heap/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/heap/src/__tests__/index.test.ts deleted file mode 100644 index 3153c7c418..0000000000 --- a/packages/browser-destinations/destinations/heap/src/__tests__/index.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import heapDestination, { destination } from '../index' -import { HEAP_TEST_ENV_ID, mockHeapJsHttpRequest } from '../test-utilities' - -const subscriptions = [ - { - partnerAction: 'trackEvent', - name: 'Track Event', - enabled: true, - subscribe: 'type = "track"', - mapping: {} - } -] - -describe('Heap', () => { - test('loading', async () => { - jest.spyOn(destination, 'initialize') - - mockHeapJsHttpRequest() - - const [event] = await heapDestination({ appId: HEAP_TEST_ENV_ID, subscriptions }) - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - expect(window.heap.appid).toEqual(HEAP_TEST_ENV_ID) - }) - test('loading with cdn', async () => { - jest.spyOn(destination, 'initialize') - - mockHeapJsHttpRequest() - - const [event] = await heapDestination({ - appId: HEAP_TEST_ENV_ID, - subscriptions, - hostname: 'cdn.heapanalytics.com', - trackingServer: 'https://heapanalytics.com' - }) - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - expect(window.heap.appid).toEqual(HEAP_TEST_ENV_ID) - }) -}) diff --git a/packages/browser-destinations/destinations/heap/src/constants.ts b/packages/browser-destinations/destinations/heap/src/constants.ts deleted file mode 100644 index efaffb18ad..0000000000 --- a/packages/browser-destinations/destinations/heap/src/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const HEAP_SEGMENT_BROWSER_LIBRARY_NAME = 'browser-destination' diff --git a/packages/browser-destinations/destinations/heap/src/generated-types.ts b/packages/browser-destinations/destinations/heap/src/generated-types.ts deleted file mode 100644 index 70f8bdb0c5..0000000000 --- a/packages/browser-destinations/destinations/heap/src/generated-types.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * The app ID of the environment to which you want to send data. You can find this ID on the [Projects](https://heapanalytics.com/app/manage/projects) page. - */ - appId: string - /** - * Setting to true will redact all target text on your website. For more information visit the heap [docs page](https://developers.heap.io/docs/web#global-data-redaction-via-disabling-text-capture). - */ - disableTextCapture?: boolean - /** - * This option is turned off by default to accommodate websites not served over HTTPS. If your application uses HTTPS, we recommend enabling secure cookies to prevent Heap cookies from being observed by unauthorized parties. For more information visit the heap [docs page](https://developers.heap.io/docs/web#securecookie). - */ - secureCookie?: boolean - /** - * This is an optional setting. This is used to set up first-party data collection. For most cased this should not be set. For more information visit the heap [docs page](https://developers.heap.io/docs/set-up-first-party-data-collection-in-heap). - */ - trackingServer?: string - /** - * This is an optional setting used to set the host that loads heap-js. This setting is used when heapJS is self-hosted. In most cased this should be left unset. The hostname should not contain https or app id it will be populated like so: https://${hostname}/js/heap-${appId}.js. For more information visit the heap [docs page](https://developers.heap.io/docs/self-hosting-heapjs). - */ - hostname?: string - /** - * This is an optional setting. When set, nested array items will be sent in as new Heap events. Defaults to 0. - */ - browserArrayLimit?: number -} diff --git a/packages/browser-destinations/destinations/heap/src/identifyUser/__tests__/index.test.ts b/packages/browser-destinations/destinations/heap/src/identifyUser/__tests__/index.test.ts deleted file mode 100644 index 5e23b8589f..0000000000 --- a/packages/browser-destinations/destinations/heap/src/identifyUser/__tests__/index.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import { - createMockedHeapJsSdk, - HEAP_TEST_ENV_ID, - identifyUserSubscription, - mockHeapJsHttpRequest -} from '../../test-utilities' -import heapDestination from '../../index' - -describe('#identify', () => { - it('should not call identify if user id is not provided and anonymous user id is provided', async () => { - mockHeapJsHttpRequest() - window.heap = createMockedHeapJsSdk() - - const [identifyUser] = await heapDestination({ appId: HEAP_TEST_ENV_ID, subscriptions: [identifyUserSubscription] }) - - await identifyUser.load(Context.system(), {} as Analytics) - const heapIdentifySpy = jest.spyOn(window.heap, 'identify') - - await identifyUser.identify?.( - new Context({ - type: 'identify', - anonymousId: 'anon', - traits: { - testProp: false - } - }) - ) - - expect(heapIdentifySpy).not.toHaveBeenCalled() - }) - - it('should call identify if user id is provided', async () => { - mockHeapJsHttpRequest() - window.heap = createMockedHeapJsSdk() - - const [identifyUser] = await heapDestination({ appId: HEAP_TEST_ENV_ID, subscriptions: [identifyUserSubscription] }) - - await identifyUser.load(Context.system(), {} as Analytics) - const heapIdentifySpy = jest.spyOn(window.heap, 'identify') - const heapAddUserPropertiesSpy = jest.spyOn(window.heap, 'addUserProperties') - - await identifyUser.identify?.( - new Context({ - type: 'identify', - anonymousId: 'anon', - userId: 'user@example.com' - }) - ) - - expect(heapIdentifySpy).toHaveBeenCalledWith('user@example.com') - expect(heapAddUserPropertiesSpy).not.toHaveBeenCalled() - }) - - it('should call addUserProprties if traits are provided', async () => { - mockHeapJsHttpRequest() - window.heap = createMockedHeapJsSdk() - - const [identifyUser] = await heapDestination({ appId: HEAP_TEST_ENV_ID, subscriptions: [identifyUserSubscription] }) - - await identifyUser.load(Context.system(), {} as Analytics) - const heapIdentifySpy = jest.spyOn(window.heap, 'identify') - const heapAddUserPropertiesSpy = jest.spyOn(window.heap, 'addUserProperties') - - await identifyUser.identify?.( - new Context({ - type: 'identify', - anonymousId: 'anon', - traits: { - testProp: false - } - }) - ) - - expect(heapIdentifySpy).not.toHaveBeenCalled() - expect(heapAddUserPropertiesSpy).toHaveBeenCalledWith({ testProp: false }) - }) -}) diff --git a/packages/browser-destinations/destinations/heap/src/identifyUser/generated-types.ts b/packages/browser-destinations/destinations/heap/src/identifyUser/generated-types.ts deleted file mode 100644 index d0bb10cfe5..0000000000 --- a/packages/browser-destinations/destinations/heap/src/identifyUser/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The user's identity - */ - userId?: string - /** - * The Segment traits to be forwarded to Heap - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/heap/src/identifyUser/index.ts b/packages/browser-destinations/destinations/heap/src/identifyUser/index.ts deleted file mode 100644 index 86df4b9dbd..0000000000 --- a/packages/browser-destinations/destinations/heap/src/identifyUser/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { HeapApi } from '../types' - -const action: BrowserActionDefinition = { - title: 'Identify User', - description: 'Sets user identity', - platform: 'web', - defaultSubscription: 'type = "identify"', - fields: { - userId: { - type: 'string', - required: false, - description: "The user's identity", - label: 'Identity', - default: { - '@path': '$.userId' - } - }, - traits: { - type: 'object', - required: false, - description: 'The Segment traits to be forwarded to Heap', - label: 'Traits', - default: { - '@path': '$.traits' - } - } - }, - perform: (heap, event) => { - if (event.payload.traits) { - heap.addUserProperties(event.payload.traits) - } - if (event.payload.userId) { - heap.identify(event.payload.userId) - } - } -} - -export default action diff --git a/packages/browser-destinations/destinations/heap/src/index.ts b/packages/browser-destinations/destinations/heap/src/index.ts deleted file mode 100644 index 6f03e1f921..0000000000 --- a/packages/browser-destinations/destinations/heap/src/index.ts +++ /dev/null @@ -1,120 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import { HeapApi, UserConfig } from './types' -import { defaultValues } from '@segment/actions-core' -import trackEvent from './trackEvent' -import identifyUser from './identifyUser' -import { isDefined } from './utils' - -declare global { - interface Window { - heap: HeapApi - } -} - -// Switch from unknown to the partner SDK client types -export const destination: BrowserDestinationDefinition = { - name: 'Heap Web (Actions)', - slug: 'actions-heap-web', - mode: 'device', - presets: [ - { - name: 'Track Event', - subscribe: 'type = "track"', - partnerAction: 'trackEvent', - mapping: defaultValues(trackEvent.fields), - type: 'automatic' - }, - { - name: 'Identify User', - subscribe: 'type = "identify"', - partnerAction: 'identifyUser', - mapping: defaultValues(identifyUser.fields), - type: 'automatic' - } - ], - settings: { - // Add any Segment destination settings required here - appId: { - label: 'Heap app ID', - description: - 'The app ID of the environment to which you want to send data. You can find this ID on the [Projects](https://heapanalytics.com/app/manage/projects) page.', - type: 'string', - required: true - }, - disableTextCapture: { - label: 'Global data redaction via Disabling Text Capture', - description: - 'Setting to true will redact all target text on your website. For more information visit the heap [docs page](https://developers.heap.io/docs/web#global-data-redaction-via-disabling-text-capture).', - type: 'boolean', - required: false - }, - secureCookie: { - label: 'Secure Cookie', - description: - 'This option is turned off by default to accommodate websites not served over HTTPS. If your application uses HTTPS, we recommend enabling secure cookies to prevent Heap cookies from being observed by unauthorized parties. For more information visit the heap [docs page](https://developers.heap.io/docs/web#securecookie).', - type: 'boolean', - required: false - }, - trackingServer: { - label: 'Tracking Server', - description: - 'This is an optional setting. This is used to set up first-party data collection. For most cased this should not be set. For more information visit the heap [docs page](https://developers.heap.io/docs/set-up-first-party-data-collection-in-heap).', - type: 'string', - required: false - }, - hostname: { - label: 'Hostname', - description: - 'This is an optional setting used to set the host that loads heap-js. This setting is used when heapJS is self-hosted. In most cased this should be left unset. The hostname should not contain https or app id it will be populated like so: https://${hostname}/js/heap-${appId}.js. For more information visit the heap [docs page](https://developers.heap.io/docs/self-hosting-heapjs).', - type: 'string', - required: false - }, - browserArrayLimit: { - label: 'Browser Array Limit', - description: - 'This is an optional setting. When set, nested array items will be sent in as new Heap events. Defaults to 0.', - type: 'number', - required: false - } - }, - - initialize: async ({ settings }, deps) => { - if (window.heap) { - return window.heap - } - - const config: UserConfig = { - disableTextCapture: settings.disableTextCapture || false, - secureCookie: settings.secureCookie || false - } - - if (settings.trackingServer) { - config.trackingServer = settings.trackingServer - } - - // heap.appid and heap.config must be set before loading heap.js. - window.heap = window.heap || [] - window.heap.appid = settings.appId - window.heap.config = config - - if (isDefined(settings.hostname)) { - await deps.loadScript(`https://${settings.hostname}/js/heap-${settings.appId}.js`) - } else { - await deps.loadScript(`https://cdn.heapanalytics.com/js/heap-${settings.appId}.js`) - } - - // Explained here: https://stackoverflow.com/questions/14859058/why-does-the-segment-io-loader-script-push-method-names-args-onto-a-queue-which - await deps.resolveWhen(() => Object.prototype.hasOwnProperty.call(window, 'heap'), 100) - - return window.heap - }, - - actions: { - trackEvent, - identifyUser - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/heap/src/test-utilities.ts b/packages/browser-destinations/destinations/heap/src/test-utilities.ts deleted file mode 100644 index 1f9f03ae09..0000000000 --- a/packages/browser-destinations/destinations/heap/src/test-utilities.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { HeapApi } from './types' -import { Subscription } from '@segment/browser-destination-runtime/types' -import nock from 'nock' - -export const HEAP_TEST_ENV_ID = '1' - -export const createMockedHeapJsSdk = (): HeapApi => { - return { - appid: HEAP_TEST_ENV_ID, - config: { - disableTextCapture: true, - secureCookie: true - }, - load: jest.fn(), - track: jest.fn(), - identify: jest.fn(), - addUserProperties: jest.fn() - } -} -export const trackEventSubscription: Subscription = { - partnerAction: 'trackEvent', - name: 'Track Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - name: { - '@path': '$.name' - }, - properties: { - '@path': '$.properties' - }, - identity: { - '@path': '$.userId' - }, - anonymousId: { - '@path': '$.anonymousId' - }, - traits: { - '@path': '$.context.traits' - } - } -} - -export const identifyUserSubscription: Subscription = { - partnerAction: 'identifyUser', - name: 'Identify User', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - anonymousId: { - '@path': '$.anonymousId' - }, - userId: { - '@path': '$.userId' - }, - traits: { - '@path': '$.traits' - } - } -} - -export const mockHeapJsHttpRequest = (): void => { - nock('https://cdn.heapanalytics.com').get(`/js/heap-${HEAP_TEST_ENV_ID}.js`).reply(200, {}) -} diff --git a/packages/browser-destinations/destinations/heap/src/trackEvent/__tests__/index.test.ts b/packages/browser-destinations/destinations/heap/src/trackEvent/__tests__/index.test.ts deleted file mode 100644 index d7ead7d208..0000000000 --- a/packages/browser-destinations/destinations/heap/src/trackEvent/__tests__/index.test.ts +++ /dev/null @@ -1,377 +0,0 @@ -import { Analytics, Context, Plugin } from '@segment/analytics-next' -import heapDestination from '../../index' -import { - createMockedHeapJsSdk, - HEAP_TEST_ENV_ID, - mockHeapJsHttpRequest, - trackEventSubscription -} from '../../test-utilities' -import { HEAP_SEGMENT_BROWSER_LIBRARY_NAME } from '../../constants' - -describe('#trackEvent', () => { - let eventWithUnrolling: Plugin - let event: Plugin - let heapTrackSpy: jest.SpyInstance - let addUserPropertiesSpy: jest.SpyInstance - let identifySpy: jest.SpyInstance - - beforeAll(async () => { - mockHeapJsHttpRequest() - window.heap = createMockedHeapJsSdk() - - eventWithUnrolling = ( - await heapDestination({ appId: HEAP_TEST_ENV_ID, subscriptions: [trackEventSubscription], browserArrayLimit: 5 }) - )[0] - await eventWithUnrolling.load(Context.system(), {} as Analytics) - - event = (await heapDestination({ appId: HEAP_TEST_ENV_ID, subscriptions: [trackEventSubscription] }))[0] - await event.load(Context.system(), {} as Analytics) - - heapTrackSpy = jest.spyOn(window.heap, 'track') - addUserPropertiesSpy = jest.spyOn(window.heap, 'addUserProperties') - identifySpy = jest.spyOn(window.heap, 'identify') - }) - - beforeEach(() => { - jest.resetAllMocks() - }) - - it('sends events to heap', async () => { - await eventWithUnrolling.track?.( - new Context({ - type: 'track', - name: 'hello!', - properties: { - products: [ - { - name: 'Test Product 1', - color: 'red', - qty: 2, - custom_vars: { - position: 0, - something_else: 'test', - another_one: ['one', 'two', 'three'] - } - }, - { - name: 'Test Product 2', - color: 'blue', - qty: 1, - custom_vars: { - position: 1, - something_else: 'blah', - another_one: ['four', 'five', 'six'] - } - } - ] - } - }) - ) - expect(heapTrackSpy).toHaveBeenCalledTimes(3) - expect(heapTrackSpy).toHaveBeenNthCalledWith(1, 'hello! products item', { - name: 'Test Product 1', - color: 'red', - qty: '2', - 'custom_vars.position': '0', - 'custom_vars.something_else': 'test', - 'custom_vars.another_one': '["one","two","three"]', - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - expect(heapTrackSpy).toHaveBeenNthCalledWith(2, 'hello! products item', { - name: 'Test Product 2', - color: 'blue', - qty: '1', - 'custom_vars.position': '1', - 'custom_vars.something_else': 'blah', - 'custom_vars.another_one': '["four","five","six"]', - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - expect(heapTrackSpy).toHaveBeenNthCalledWith(3, 'hello!', { - products: - '[{"name":"Test Product 1","color":"red","qty":2,"custom_vars":{"position":0,"something_else":"test","another_one":["one","two","three"]}},{"name":"Test Product 2","color":"blue","qty":1,"custom_vars":{"position":1,"something_else":"blah","another_one":["four","five","six"]}}]', - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - expect(addUserPropertiesSpy).toHaveBeenCalledTimes(0) - expect(identifySpy).toHaveBeenCalledTimes(0) - }) - - it('limits number of properties in array', async () => { - await eventWithUnrolling.track?.( - new Context({ - type: 'track', - name: 'hello!', - properties: { - testArray1: [{ val: 1 }, { val: 2 }, { val: 3 }], - testArray2: [{ val: 4 }, { val: 5 }, { val: 'N/A' }] - } - }) - ) - expect(heapTrackSpy).toHaveBeenCalledTimes(6) - - for (let i = 1; i <= 3; i++) { - expect(heapTrackSpy).toHaveBeenNthCalledWith(i, 'hello! testArray1 item', { - val: i.toString(), - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - } - for (let i = 4; i <= 5; i++) { - expect(heapTrackSpy).toHaveBeenNthCalledWith(i, 'hello! testArray2 item', { - val: i.toString(), - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - } - expect(heapTrackSpy).toHaveBeenNthCalledWith(6, 'hello!', { - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME, - testArray1: '[{"val":1},{"val":2},{"val":3}]', - testArray2: '[{"val":4},{"val":5},{"val":"N/A"}]' - }) - }) - - it('does not limit number of properties if browserArrayLimit is 0', async () => { - await event.track?.( - new Context({ - type: 'track', - name: 'hello!', - properties: { - testArray1: [{ val: 1 }, { val: 2 }, { val: 3 }], - testArray2: [{ val: 4 }, { val: 5 }, { val: 'N/A' }] - } - }) - ) - expect(heapTrackSpy).toHaveBeenCalledTimes(1) - - expect(heapTrackSpy).toHaveBeenCalledWith('hello!', { - testArray1: '[{"val":1},{"val":2},{"val":3}]', - testArray2: '[{"val":4},{"val":5},{"val":"N/A"}]', - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - }) - - it('should stringify array', async () => { - await event.track?.( - new Context({ - type: 'track', - name: 'hello!', - properties: { - testArray1: ['test', 'testing', 'tester'] - } - }) - ) - expect(heapTrackSpy).toHaveBeenCalledTimes(1) - - expect(heapTrackSpy).toHaveBeenCalledWith('hello!', { - testArray1: '["test","testing","tester"]', - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - }) - - it('should flatten properties', async () => { - await event.track?.( - new Context({ - type: 'track', - name: 'hello!', - properties: { - isAutomated: true, - isClickable: true, - custom_vars: { - bodyText: 'Testing text', - ctaText: 'Click me', - position: 0, - testNestedValues: { - count: 5, - color: 'green' - } - } - } - }) - ) - expect(heapTrackSpy).toHaveBeenCalledWith('hello!', { - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME, - isAutomated: 'true', - isClickable: 'true', - 'custom_vars.bodyText': 'Testing text', - 'custom_vars.ctaText': 'Click me', - 'custom_vars.position': '0', - 'custom_vars.testNestedValues.count': '5', - 'custom_vars.testNestedValues.color': 'green' - }) - }) - - it('should flatten properties on parent when browserArrayLimit is set', async () => { - await eventWithUnrolling.track?.( - new Context({ - type: 'track', - name: 'hello!', - properties: { - boolean_test: false, - string_test: 'react', - number_test: 0, - custom_vars: { - property: 1 - } - } - }) - ) - expect(heapTrackSpy).toHaveBeenCalledWith('hello!', { - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME, - boolean_test: 'false', - string_test: 'react', - number_test: '0', - 'custom_vars.property': '1' - }) - }) - - it('should send segment_library property if no other properties were provided', async () => { - await event.track?.( - new Context({ - type: 'track', - name: 'hello!' - }) - ) - - expect(heapTrackSpy).toHaveBeenCalledWith('hello!', { - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - expect(addUserPropertiesSpy).toHaveBeenCalledTimes(0) - expect(identifySpy).toHaveBeenCalledTimes(0) - }) - - it('should not override segment_library property value if provided by user', async () => { - const segmentLibraryValue = 'user-provided-value' - const userId = 'TEST_ID77' - await event.track?.( - new Context({ - type: 'track', - name: 'hello!', - properties: { - segment_library: segmentLibraryValue - }, - userId - }) - ) - - expect(heapTrackSpy).toHaveBeenCalledWith('hello!', { - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - expect(identifySpy).toHaveBeenCalledWith(userId) - expect(addUserPropertiesSpy).toHaveBeenCalledTimes(0) - }) - - it('should add traits', async () => { - const segmentLibraryValue = 'test123' - const anonymous_id = 'ANON1' - const name = 'Grace Hopper' - await event.track?.( - new Context({ - type: 'track', - name: 'hello!', - properties: { - segment_library: segmentLibraryValue - }, - context: { - traits: { - name - } - }, - anonymousId: anonymous_id - }) - ) - - expect(heapTrackSpy).toHaveBeenCalledWith('hello!', { - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - expect(addUserPropertiesSpy).toHaveBeenCalledWith({ - anonymous_id, - name - }) - expect(identifySpy).toHaveBeenCalledTimes(0) - }) - - describe('data tests', () => { - it('should unroll and flatten', async () => { - await eventWithUnrolling.track?.( - new Context({ - type: 'track', - name: 'Product List Viewed', - properties: { - membership_status: 'lead', - products: [ - { - sku: 'PT2252152-0001-00', - url: '/products/THE-ONE-JOGGER-PT2252152-0001-2', - variant: 'Black', - vip_price: 59.95, - membership_brand_id: 1, - quantity: 1 - }, - { - sku: 'PT2252152-4846-00', - url: '/products/THE-ONE-JOGGER-PT2252152-4846', - variant: 'Deep Navy', - vip_price: 59.95, - membership_brand_id: 1, - quantity: 1 - }, - { - sku: 'PT2458220-0001-00', - url: '/products/THE-YEAR-ROUND-TERRY-JOGGER-PT2458220-0001', - variant: 'Black', - vip_price: 59.95, - membership_brand_id: 1, - quantity: 1 - } - ], - store_group_id: '16', - session_id: '14322962105', - user_status_initial: 'lead', - utm_campaign: null, - utm_medium: null, - utm_source: null, - customer_id: '864832720' - } - }) - ) - expect(heapTrackSpy).toHaveBeenCalledTimes(4) - expect(heapTrackSpy).toHaveBeenNthCalledWith(1, 'Product List Viewed products item', { - sku: 'PT2252152-0001-00', - url: '/products/THE-ONE-JOGGER-PT2252152-0001-2', - variant: 'Black', - vip_price: '59.95', - membership_brand_id: '1', - quantity: '1', - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - expect(heapTrackSpy).toHaveBeenNthCalledWith(2, 'Product List Viewed products item', { - sku: 'PT2252152-4846-00', - url: '/products/THE-ONE-JOGGER-PT2252152-4846', - variant: 'Deep Navy', - vip_price: '59.95', - membership_brand_id: '1', - quantity: '1', - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - expect(heapTrackSpy).toHaveBeenNthCalledWith(3, 'Product List Viewed products item', { - sku: 'PT2458220-0001-00', - url: '/products/THE-YEAR-ROUND-TERRY-JOGGER-PT2458220-0001', - variant: 'Black', - vip_price: '59.95', - membership_brand_id: '1', - quantity: '1', - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - expect(heapTrackSpy).toHaveBeenNthCalledWith(4, 'Product List Viewed', { - membership_status: 'lead', - products: - '[{"sku":"PT2252152-0001-00","url":"/products/THE-ONE-JOGGER-PT2252152-0001-2","variant":"Black","vip_price":59.95,"membership_brand_id":1,"quantity":1},{"sku":"PT2252152-4846-00","url":"/products/THE-ONE-JOGGER-PT2252152-4846","variant":"Deep Navy","vip_price":59.95,"membership_brand_id":1,"quantity":1},{"sku":"PT2458220-0001-00","url":"/products/THE-YEAR-ROUND-TERRY-JOGGER-PT2458220-0001","variant":"Black","vip_price":59.95,"membership_brand_id":1,"quantity":1}]', - store_group_id: '16', - session_id: '14322962105', - user_status_initial: 'lead', - utm_campaign: null, - utm_medium: null, - utm_source: null, - customer_id: '864832720', - segment_library: HEAP_SEGMENT_BROWSER_LIBRARY_NAME - }) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/heap/src/trackEvent/generated-types.ts b/packages/browser-destinations/destinations/heap/src/trackEvent/generated-types.ts deleted file mode 100644 index f61119c936..0000000000 --- a/packages/browser-destinations/destinations/heap/src/trackEvent/generated-types.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The name of the event. - */ - name: string - /** - * A JSON object containing additional information about the event that will be indexed by Heap. - */ - properties?: { - [k: string]: unknown - } - /** - * a string that uniquely identifies a user, such as an email, handle, or username. This means no two users in one environment may share the same identity. More on identify: https://developers.heap.io/docs/using-identify - */ - identity?: string - /** - * The segment anonymous identifier for the user - */ - anonymousId?: string - /** - * An object with key-value properties you want associated with the user. Each property must either be a number or string with fewer than 1024 characters. - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/heap/src/trackEvent/index.ts b/packages/browser-destinations/destinations/heap/src/trackEvent/index.ts deleted file mode 100644 index ce9cbce6f0..0000000000 --- a/packages/browser-destinations/destinations/heap/src/trackEvent/index.ts +++ /dev/null @@ -1,141 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { HeapApi } from '../types' -import { HEAP_SEGMENT_BROWSER_LIBRARY_NAME } from '../constants' -import { isDefined, flat, flattenProperties } from '../utils' - -const action: BrowserActionDefinition = { - title: 'Track Event', - description: 'Track events', - platform: 'web', - defaultSubscription: 'type = "track"', - fields: { - name: { - description: 'The name of the event.', - label: 'Name', - required: true, - type: 'string', - default: { - '@path': '$.event' - } - }, - properties: { - description: 'A JSON object containing additional information about the event that will be indexed by Heap.', - label: 'Properties', - required: false, - type: 'object', - default: { - '@path': '$.properties' - } - }, - identity: { - type: 'string', - required: false, - label: 'Identity', - description: - 'a string that uniquely identifies a user, such as an email, handle, or username. This means no two users in one environment may share the same identity. More on identify: https://developers.heap.io/docs/using-identify' - }, - anonymousId: { - type: 'string', - required: false, - description: 'The segment anonymous identifier for the user', - label: 'Anonymous ID', - default: { - '@path': '$.anonymousId' - } - }, - traits: { - label: 'User Properties', - type: 'object', - description: - 'An object with key-value properties you want associated with the user. Each property must either be a number or string with fewer than 1024 characters.', - default: { - '@path': '$.context.traits' - } - } - }, - perform: (heap, event) => { - // Add user properties - if (event.payload.anonymousId || isDefined(event.payload?.traits)) { - const traits = flat(event.payload?.traits) - heap.addUserProperties({ - ...(isDefined(event.payload.anonymousId) && { anonymous_id: event.payload.anonymousId }), - ...(isDefined(traits) && traits) - }) - } - - // Identify user - if (event.payload?.identity && isDefined(event.payload?.identity)) { - heap.identify(event.payload.identity) - } - - // Track Events - let eventProperties = Object.assign({}, event.payload.properties) - const eventName = event.payload.name - const browserArrayLimit = event.settings.browserArrayLimit || 0 - const browserArrayLimitSet = !!browserArrayLimit - - if (browserArrayLimitSet) { - eventProperties = heapTrackArrays(heap, eventName, eventProperties, browserArrayLimit) - } else { - eventProperties = flattenProperties(eventProperties) - } - - heapTrack(heap, eventName, eventProperties) - } -} - -const heapTrackArrays = ( - heap: HeapApi, - eventName: string, - properties: { - [k: string]: unknown - }, - browserArrayLimit: number -) => { - let eventProperties = Object.assign({}, properties) - let arrayEventsCount = 0 - for (const [key, value] of Object.entries(eventProperties)) { - if (arrayEventsCount >= browserArrayLimit) { - return eventProperties - } - - delete eventProperties[key] - eventProperties = { ...eventProperties, ...flat({ [key]: value }) } - - if (!Array.isArray(value)) { - continue - } - - const arrayLength = value.length - let arrayPropertyValues - // truncate in case there are multiple array properties - if (arrayLength + arrayEventsCount > browserArrayLimit) { - arrayPropertyValues = value.splice(0, browserArrayLimit - arrayEventsCount) - } else { - arrayPropertyValues = value - } - - arrayEventsCount += arrayLength - - arrayPropertyValues.forEach((arrayPropertyValue) => { - const arrayProperties = flattenProperties(arrayPropertyValue) - heapTrack(heap, `${eventName} ${key} item`, arrayProperties) - }) - } - return eventProperties -} - -const heapTrack = ( - heap: HeapApi, - eventName: string, - properties: { - [k: string]: unknown - } -) => { - properties.segment_library = HEAP_SEGMENT_BROWSER_LIBRARY_NAME - heap.track(eventName, properties) -} - -export default action diff --git a/packages/browser-destinations/destinations/heap/src/types.ts b/packages/browser-destinations/destinations/heap/src/types.ts deleted file mode 100644 index 05b9014b8a..0000000000 --- a/packages/browser-destinations/destinations/heap/src/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -export type UserConfig = { - trackingServer?: string - disableTextCapture: boolean - secureCookie: boolean -} - -type UserProperties = { - [k: string]: unknown -} - -type EventProperties = { - [key: string]: unknown -} - -export type HeapApi = { - appid: string - track: (eventName: string, eventProperties: EventProperties, library?: string) => void - load: () => void - config: UserConfig - identify: (identity: string) => void - addUserProperties: (properties: UserProperties) => void -} diff --git a/packages/browser-destinations/destinations/heap/src/utils.ts b/packages/browser-destinations/destinations/heap/src/utils.ts deleted file mode 100644 index 52e89bd178..0000000000 --- a/packages/browser-destinations/destinations/heap/src/utils.ts +++ /dev/null @@ -1,55 +0,0 @@ -export function isDefined(value: string | undefined | null | number | object): boolean { - if (typeof value === 'object') { - return !!value && Object.keys(value).length !== 0 - } - return !(value === undefined || value === null || value === '' || value === 0 || value === '0') -} - -export type Properties = { - [k: string]: unknown -} - -type FlattenProperties = object & { - [k: string]: string | null -} - -export function flat(data?: Properties, prefix = ''): FlattenProperties | undefined { - if (!isDefined(data)) { - return undefined - } - let result: FlattenProperties = {} - for (const key in data) { - if (typeof data[key] == 'object' && data[key] !== null && !Array.isArray(data[key])) { - const flatten = flat(data[key] as Properties, prefix + '.' + key) - result = { ...result, ...flatten } - } else { - const stringifiedValue = stringify(data[key]) - result[(prefix + '.' + key).replace(/^\./, '')] = stringifiedValue - } - } - return result -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const flattenProperties = (arrayPropertyValue: any) => { - let arrayProperties = {} - for (const [key, value] of Object.entries(arrayPropertyValue)) { - if (typeof value == 'object' && value !== null) { - arrayProperties = { ...arrayProperties, ...flat({ [key]: value as Properties }) } - } else { - const stringifiedValue = stringify(value) - arrayProperties = Object.assign(arrayProperties, { [key]: stringifiedValue }) - } - } - return arrayProperties -} - -function stringify(value: unknown): string | null { - if (typeof value === 'string' || value === null) { - return value - } - if (typeof value === 'number' || typeof value === 'boolean') { - return value.toString() - } - return JSON.stringify(value) -} diff --git a/packages/browser-destinations/destinations/heap/tsconfig.json b/packages/browser-destinations/destinations/heap/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/heap/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/hubble-web/README.md b/packages/browser-destinations/destinations/hubble-web/README.md deleted file mode 100644 index b4884b277e..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# @segment/analytics-browser-hubble-web - -The Hubble (actions) browser action destination for use with @segment/analytics-next. - -## License - -MIT License - -Copyright (c) 2024 Segment - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -## Contributing - -All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. diff --git a/packages/browser-destinations/destinations/hubble-web/package.json b/packages/browser-destinations/destinations/hubble-web/package.json deleted file mode 100644 index e35e62bcea..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@segment/analytics-browser-hubble-web", - "version": "1.33.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/actions-core": "^3.116.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/hubble-web/src/__tests__/__snapshots__/index.test.ts.snap b/packages/browser-destinations/destinations/hubble-web/src/__tests__/__snapshots__/index.test.ts.snap deleted file mode 100644 index ec0642738e..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/__tests__/__snapshots__/index.test.ts.snap +++ /dev/null @@ -1,16 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Hubble load Hubble SDK: - - 1`] = ` -NodeList [ - , -] -`; diff --git a/packages/browser-destinations/destinations/hubble-web/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/hubble-web/src/__tests__/index.test.ts deleted file mode 100644 index ebd9421846..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/__tests__/index.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import hubbleDestination, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - name: 'Identify user', - subscribe: 'type = "identify"', - partnerAction: 'identify', - enabled: true, - mapping: { - userId: { - type: 'string', - required: true, - label: 'User ID', - description: 'Unique user ID', - default: { - '@path': '$.userId' - } - }, - anonymousId: { - type: 'string', - required: false, - description: 'Anonymous id of the user', - label: 'Anonymous ID', - default: { - '@path': '$.anonymousId' - } - }, - attributes: { - type: 'object', - required: false, - description: 'User traits used to enrich user identification', - label: 'Traits', - default: { - '@path': '$.traits' - } - } - } - }, - { - name: 'Track event', - subscribe: 'type = "track"', - partnerAction: 'track', - enabled: true, - mapping: { - event: { - description: 'Event to be tracked', - label: 'Event', - required: true, - type: 'string', - default: { - '@path': '$.event' - } - }, - attributes: { - description: 'Object containing the attributes (properties) of the event', - type: 'object', - required: false, - label: 'Event Attributes', - default: { - '@path': '$.properties' - } - } - } - } -] - -describe('Hubble', () => { - beforeAll(() => { - jest.mock('@segment/browser-destination-runtime/load-script', () => ({ - loadScript: (_src: any, _attributes: any) => {} - })) - jest.mock('@segment/browser-destination-runtime/resolve-when', () => ({ - resolveWhen: (_fn: any, _timeout: any) => {} - })) - }) - - const testID = 'testId' - - test('load Hubble SDK', async () => { - const [event] = await hubbleDestination({ - id: testID, - subscriptions - }) - - jest.spyOn(destination, 'initialize') - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - const scripts = window.document.querySelectorAll('script') - expect(scripts).toMatchSnapshot(` - - `) - }) -}) diff --git a/packages/browser-destinations/destinations/hubble-web/src/generated-types.ts b/packages/browser-destinations/destinations/hubble-web/src/generated-types.ts deleted file mode 100644 index eef1f71582..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * Unique identifier for your team (given in Hubble app) - */ - id: string -} diff --git a/packages/browser-destinations/destinations/hubble-web/src/identify/__tests__/index.test.ts b/packages/browser-destinations/destinations/hubble-web/src/identify/__tests__/index.test.ts deleted file mode 100644 index f7cfa89e93..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/identify/__tests__/index.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import hubbleDestination, { destination } from '../../index' -import { Subscription } from '@segment/browser-destination-runtime/types' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'identify', - name: 'Identify User', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - anonymousId: { - '@path': '$.anonymousId' - }, - userId: { - '@path': '$.userId' - }, - attributes: { - '@path': '$.traits' - } - } - } -] - -describe('identify', () => { - beforeAll(() => { - jest.mock('@segment/browser-destination-runtime/load-script', () => ({ - loadScript: (_src: any, _attributes: any) => {} - })) - jest.mock('@segment/browser-destination-runtime/resolve-when', () => ({ - resolveWhen: (_fn: any, _timeout: any) => {} - })) - }) - - let identify: any - const mockIdentify: jest.Mock = jest.fn() - - beforeEach(async () => { - const [hubbleIdentify] = await hubbleDestination({ - id: 'testID', - subscriptions - }) - - identify = hubbleIdentify - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - const mockedWithTrack = { - id: 'testID', - initialized: true, - emitter: { setSource: jest.fn() }, - track: mockIdentify, - identify: jest.fn(), - setSource: jest.fn() - } - return Promise.resolve(mockedWithTrack) - }) - await identify.load(Context.system(), {} as Analytics) - }) - - test('it maps event parameters correctly to identify function ', async () => { - jest.spyOn(destination.actions.identify, 'perform') - await identify.load(Context.system(), {} as Analytics) - - await identify.identify?.( - new Context({ - type: 'identify', - anonymousId: 'anon-123', - userId: 'some-user-123', - traits: { - someNumber: 123, - hello: 'world', - email: 'this_email@hubble.team' - } - }) - ) - - expect(destination.actions.identify.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - anonymousId: 'anon-123', - userId: 'some-user-123', - attributes: { - someNumber: 123, - hello: 'world', - email: 'this_email@hubble.team' - } - } - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/hubble-web/src/identify/generated-types.ts b/packages/browser-destinations/destinations/hubble-web/src/identify/generated-types.ts deleted file mode 100644 index a3a0d93825..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/identify/generated-types.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * Unique identifer of the user - */ - userId?: string - /** - * Anonymous identifier of the user - */ - anonymousId?: string - /** - * User traits used to enrich user identification - */ - attributes?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/hubble-web/src/identify/index.ts b/packages/browser-destinations/destinations/hubble-web/src/identify/index.ts deleted file mode 100644 index 8122a46a17..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/identify/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import { Hubble } from '../types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Identify', - description: 'Set identifiers and attributes for a user', - platform: 'web', - defaultSubscription: 'type = "identify"', - fields: { - userId: { - description: 'Unique identifer of the user', - type: 'string', - required: false, - label: 'User ID', - default: { - '@path': '$.userId' - } - }, - anonymousId: { - description: 'Anonymous identifier of the user', - type: 'string', - required: false, - label: 'Anonymous ID', - default: { - '@path': '$.anonymousId' - } - }, - attributes: { - description: 'User traits used to enrich user identification', - type: 'object', - required: false, - label: 'User Attributes (Traits)', - default: { - '@path': '$.traits' - } - } - }, - perform: (hubble, event) => { - const payload = event.payload - - hubble.identify && - hubble.identify({ userId: payload.userId, anonymousId: payload.anonymousId, attributes: payload.attributes }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/hubble-web/src/index.ts b/packages/browser-destinations/destinations/hubble-web/src/index.ts deleted file mode 100644 index adef7740f4..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' - -import { Hubble } from './types' -import { defaultValues } from '@segment/actions-core' - -import track from './track' -import identify from './identify' - -declare global { - interface Window { - Hubble: Hubble - } -} - -export const destination: BrowserDestinationDefinition = { - name: 'Hubble (actions)', - slug: 'hubble-web', - mode: 'device', - description: - 'From design to production, monitor, measure and enhance your user experience with seamless integration with Segment', - presets: [ - { - name: 'Identify user', - subscribe: 'type = "identify"', - partnerAction: 'identify', - mapping: defaultValues(identify.fields), - type: 'automatic' - }, - { - name: 'Track event', - subscribe: 'type = "track"', - partnerAction: 'track', - mapping: defaultValues(track.fields), - type: 'automatic' - } - ], - - settings: { - id: { - description: 'Unique identifier for your team (given in Hubble app)', - label: 'id', - type: 'string', - required: true - } - }, - - initialize: async ({ settings }, deps) => { - await deps.loadScript(`https://sdk.hubble.team/api/sdk/${settings.id}`) - await deps.resolveWhen(() => window?.Hubble?.initialized, 250) - - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - window?.Hubble?.setSource('__segment__') - return window.Hubble - }, - - actions: { - track, - identify - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/hubble-web/src/track/__tests__/index.test.ts b/packages/browser-destinations/destinations/hubble-web/src/track/__tests__/index.test.ts deleted file mode 100644 index b6f29b62ec..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/track/__tests__/index.test.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import hubbleDestination, { destination } from '../../index' -import { Subscription } from '@segment/browser-destination-runtime/types' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'track', - name: 'Track event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - event: { - '@path': '$.event' - }, - attributes: { - '@path': '$.properties' - } - } - } -] - -describe('track', () => { - beforeAll(() => { - jest.mock('@segment/browser-destination-runtime/load-script', () => ({ - loadScript: (_src: any, _attributes: any) => {} - })) - jest.mock('@segment/browser-destination-runtime/resolve-when', () => ({ - resolveWhen: (_fn: any, _timeout: any) => {} - })) - }) - - let track: any - const mockTrack: jest.Mock = jest.fn() - - beforeEach(async () => { - const [hubbleTrack] = await hubbleDestination({ - id: 'testID', - subscriptions - }) - - track = hubbleTrack - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - const mockedWithTrack = { - id: 'testID', - initialized: true, - emitter: { setSource: jest.fn() }, - track: mockTrack, - identify: jest.fn(), - setSource: jest.fn() - } - return Promise.resolve(mockedWithTrack) - }) - await track.load(Context.system(), {} as Analytics) - }) - - test('it maps event parameters correctly to track function', async () => { - jest.spyOn(destination.actions.track, 'perform') - - await track.track?.( - new Context({ - type: 'track', - event: 'event-test', - properties: { - prop1: 'something', - prop2: 'another-thing' - } - }) - ) - - expect(destination.actions.track.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - event: 'event-test', - attributes: { - prop1: 'something', - prop2: 'another-thing' - } - } - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/hubble-web/src/track/generated-types.ts b/packages/browser-destinations/destinations/hubble-web/src/track/generated-types.ts deleted file mode 100644 index 95b0d403de..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/track/generated-types.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * Event to be tracked - */ - event: string - /** - * Object containing the attributes (properties) of the event - */ - attributes?: { - [k: string]: unknown - } - /** - * Unique identifer of the user - */ - userId?: string - /** - * Anonymous identifier of the user - */ - anonymousId?: string -} diff --git a/packages/browser-destinations/destinations/hubble-web/src/track/index.ts b/packages/browser-destinations/destinations/hubble-web/src/track/index.ts deleted file mode 100644 index ffbf3fad2b..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/track/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import { Hubble } from '../types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Track', - description: 'Track events to trigger Hubble surveys', - platform: 'web', - defaultSubscription: 'type = "track"', - fields: { - event: { - description: 'Event to be tracked', - label: 'Event', - required: true, - type: 'string', - default: { - '@path': '$.event' - } - }, - attributes: { - description: 'Object containing the attributes (properties) of the event', - type: 'object', - required: false, - label: 'Event Attributes', - default: { - '@path': '$.properties' - } - }, - userId: { - description: 'Unique identifer of the user', - type: 'string', - required: false, - label: 'User ID', - default: { - '@path': '$.userId' - } - }, - anonymousId: { - description: 'Anonymous identifier of the user', - type: 'string', - required: false, - label: 'Anonymous ID', - default: { - '@path': '$.anonymousId' - } - } - }, - perform: (hubble, event) => { - const payload = event.payload - - hubble.track && - hubble.track({ - event: payload.event, - attributes: payload.attributes, - userId: payload.userId, - anonymousId: payload.anonymousId - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/hubble-web/src/types.ts b/packages/browser-destinations/destinations/hubble-web/src/types.ts deleted file mode 100644 index 5e172e079b..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/src/types.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type Methods = { - track?: (...args: unknown[]) => unknown - identify?: (...args: unknown[]) => unknown -} - -export type Hubble = { - id: string - initialized: boolean - setSource: (source: string) => void -} & Methods diff --git a/packages/browser-destinations/destinations/hubble-web/tsconfig.json b/packages/browser-destinations/destinations/hubble-web/tsconfig.json deleted file mode 100644 index c2a7897afd..0000000000 --- a/packages/browser-destinations/destinations/hubble-web/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} diff --git a/packages/browser-destinations/destinations/hubspot-web/package.json b/packages/browser-destinations/destinations/hubspot-web/package.json deleted file mode 100644 index d622a90725..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-hubspot", - "version": "1.47.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/actions-core": "^3.116.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/hubspot-web/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/hubspot-web/src/__tests__/index.test.ts deleted file mode 100644 index fdcb5c06e0..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/__tests__/index.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import hubspotDestination, { destination } from '../index' -import nock from 'nock' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'trackCustomBehavioralEvent', - name: 'Track Custom Behavioral Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - event_name: { - '@path': '$.event' - } - } - } -] - -describe('Hubspot Web (Actions)', () => { - beforeEach(() => { - nock('https://js.hs-scripts.com/').get('/12345.js').reply(200, "window._hsq = '🇺🇸'") - nock('https://js-eu1.hs-scripts.com/').get('/12345.js').reply(200, "window._hsq = '🇪🇺'") - nock('https://https://js.hsforms.net').get('forms/v2.js').reply(200, "window.hbspt = {forms: '1232'}") - }) - test('loads hubspot analytics with just a HubID', async () => { - const [event] = await hubspotDestination({ - portalId: '12345', - subscriptions - }) - - jest.spyOn(destination, 'initialize') - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - expect(window._hsq).toEqual('🇺🇸') - expect(window.hbspt).toBeUndefined() - }) - - test('loads hubspot analytics with EU script', async () => { - const [event] = await hubspotDestination({ - portalId: '12345', - enableEuropeanDataCenter: true, - subscriptions - }) - - jest.spyOn(destination, 'initialize') - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window._hsq).toEqual('🇪🇺') - expect(window.hbspt).toBeUndefined() - }) - - test('loads hubspot forms SDK', async () => { - const [event] = await hubspotDestination({ - portalId: '12345', - loadFormsSDK: true, - subscriptions - }) - jest.spyOn(destination, 'initialize') - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window._hsq).toEqual('🇺🇸') - expect(window.hbspt).toBeDefined() - }) -}) diff --git a/packages/browser-destinations/destinations/hubspot-web/src/generated-types.ts b/packages/browser-destinations/destinations/hubspot-web/src/generated-types.ts deleted file mode 100644 index 863f637464..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/generated-types.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * The Hub ID of your HubSpot account. - */ - portalId: string - /** - * Enable this option if you would like Segment to load the HubSpot SDK for EU data residency. - */ - enableEuropeanDataCenter?: boolean - /** - * Enable this option to fire a `trackPageView` HubSpot event immediately after each Segment `identify` call to flush the data to HubSpot immediately. - */ - flushIdentifyImmediately?: boolean - /** - * Format the event names for custom behavioral event automatically to standard HubSpot format (`pe_event_name`). - */ - formatCustomBehavioralEventNames?: boolean - /** - * Enable this option if you would like Segment to automatically load the HubSpot Forms SDK onto your site. - */ - loadFormsSDK?: boolean -} diff --git a/packages/browser-destinations/destinations/hubspot-web/src/index.ts b/packages/browser-destinations/destinations/hubspot-web/src/index.ts deleted file mode 100644 index d327613318..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/index.ts +++ /dev/null @@ -1,115 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' - -import trackCustomBehavioralEvent from './trackCustomBehavioralEvent' - -import trackPageView from './trackPageView' - -import upsertContact from './upsertContact' -import type { Hubspot } from './types' -import { defaultValues } from '@segment/actions-core' - -declare global { - interface Window { - _hsq: any - hbspt: any - } -} - -// Switch from unknown to the partner SDK client types -export const destination: BrowserDestinationDefinition = { - name: 'Hubspot Web (Actions)', - slug: 'actions-hubspot-web', - mode: 'device', - presets: [ - { - name: 'Track Custom Behavioral Event', - subscribe: 'type = "track"', - partnerAction: 'trackCustomBehavioralEvent', - mapping: defaultValues(trackCustomBehavioralEvent.fields), - type: 'automatic' - }, - { - name: 'Upsert Contact', - subscribe: 'type = "identify"', - partnerAction: 'upsertContact', - mapping: defaultValues(upsertContact.fields), - type: 'automatic' - }, - { - name: 'Track Page View', - subscribe: 'type = "page"', - partnerAction: 'trackPageView', - mapping: defaultValues(trackPageView.fields), - type: 'automatic' - } - ], - settings: { - portalId: { - description: 'The Hub ID of your HubSpot account.', - label: 'Hub ID', - type: 'string', - required: true - }, - enableEuropeanDataCenter: { - description: 'Enable this option if you would like Segment to load the HubSpot SDK for EU data residency.', - label: 'Enable the European Data Center SDK.', - type: 'boolean', - required: false - }, - flushIdentifyImmediately: { - description: - 'Enable this option to fire a `trackPageView` HubSpot event immediately after each Segment `identify` call to flush the data to HubSpot immediately.', - label: 'Flush Identify Calls Immediately', - type: 'boolean', - required: false - }, - formatCustomBehavioralEventNames: { - description: - 'Format the event names for custom behavioral event automatically to standard HubSpot format (`pe_event_name`).', - label: 'Format Custom Behavioral Event Names', - type: 'boolean', - required: false, - default: true - }, - loadFormsSDK: { - description: - 'Enable this option if you would like Segment to automatically load the HubSpot Forms SDK onto your site.', - label: 'Load Forms SDK', - type: 'boolean', - required: false, - default: false - } - }, - - initialize: async ({ settings }, deps) => { - const scriptPath = settings.enableEuropeanDataCenter - ? `https://js-eu1.hs-scripts.com/${settings.portalId}.js` - : `https://js.hs-scripts.com/${settings.portalId}.js` - - const formsScriptPath = settings.enableEuropeanDataCenter - ? 'https://js-eu1.hsforms.net/forms/v2.js' - : 'https://js.hsforms.net/forms/v2.js' - - await deps.loadScript(scriptPath) - if (settings.loadFormsSDK) { - await deps.loadScript(formsScriptPath) - } - await deps.resolveWhen( - () => - !!(window._hsq && window._hsq.push !== Array.prototype.push) && - (!settings.loadFormsSDK || !!(window.hbspt && window.hbspt.forms)), - 100 - ) - return window._hsq - }, - - actions: { - trackCustomBehavioralEvent, - trackPageView, - upsertContact - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/hubspot-web/src/trackCustomBehavioralEvent/__tests__/index.test.ts b/packages/browser-destinations/destinations/hubspot-web/src/trackCustomBehavioralEvent/__tests__/index.test.ts deleted file mode 100644 index 679623cb43..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/trackCustomBehavioralEvent/__tests__/index.test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime' -import hubspotDestination, { destination } from '../../index' -import { Hubspot } from '../../types' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'trackCustomBehavioralEvent', - name: 'Track Custom Behavioral Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - name: { - '@path': '$.event' - }, - properties: { - '@path': '$.properties' - } - } - } -] - -describe('Hubspot.trackCustomBehavioralEvent', () => { - const settings = { - portalId: '1234', - formatCustomBehavioralEventNames: true - } - - let mockHubspot: Hubspot - let trackCustomBehavioralEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackCustomBehavioralEventPlugin] = await hubspotDestination({ - ...settings, - subscriptions - }) - trackCustomBehavioralEvent = trackCustomBehavioralEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockHubspot = { - push: jest.fn() - } - return Promise.resolve(mockHubspot) - }) - await trackCustomBehavioralEvent.load(Context.system(), {} as Analytics) - }) - - test('maps custom traits correctly', async () => { - const context = new Context({ - type: 'track', - event: 'purchased a 🍱', - properties: { - type: '🍣', - price: '$12.00', - currency: 'USD' - } - }) - await trackCustomBehavioralEvent.track?.(context) - - expect(mockHubspot.push).toHaveBeenCalledWith([ - 'trackCustomBehavioralEvent', - { name: 'pe1234_purchased_a_🍱', properties: { currency: 'USD', price: '$12.00', type: '🍣' } } - ]) - }) - - test('flattens nested object properties', async () => { - const context = new Context({ - type: 'track', - event: 'purchased a 🍱', - properties: { - type: '🍣', - price: '$12.00', - currency: 'USD', - sides: { - item1: '🧉', - item2: '🧋', - 'auxilery Sauces': { - 'Soy Sauce': '🍶' - } - } - } - }) - await trackCustomBehavioralEvent.track?.(context) - - expect(mockHubspot.push).toHaveBeenCalledWith([ - 'trackCustomBehavioralEvent', - { - name: 'pe1234_purchased_a_🍱', - properties: { - currency: 'USD', - price: '$12.00', - type: '🍣', - sides_item1: '🧉', - sides_item2: '🧋', - sides_auxilery_sauces_soy_sauce: '🍶' - } - } - ]) - }) - - test('snake case spaces and dots', async () => { - const context = new Context({ - type: 'track', - event: 'purchased a 🍱', - properties: { - type: '🍣', - price: '$12.00', - currency: 'USD', - 'type of fish': '🐟', - 'brown.rice': false - } - }) - await trackCustomBehavioralEvent.track?.(context) - - expect(mockHubspot.push).toHaveBeenCalledWith([ - 'trackCustomBehavioralEvent', - { - name: 'pe1234_purchased_a_🍱', - properties: { currency: 'USD', price: '$12.00', type: '🍣', type_of_fish: '🐟', brown_rice: false } - } - ]) - }) -}) diff --git a/packages/browser-destinations/destinations/hubspot-web/src/trackCustomBehavioralEvent/generated-types.ts b/packages/browser-destinations/destinations/hubspot-web/src/trackCustomBehavioralEvent/generated-types.ts deleted file mode 100644 index 62a478a881..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/trackCustomBehavioralEvent/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The internal event name assigned by HubSpot. This can be found in your HubSpot account. If the "Format Custom Behavioral Event Names" setting is enabled, Segment will automatically convert your Segment event name into the expected HubSpot internal event name format. - */ - name: string - /** - * A list of key-value pairs that describe the event. - */ - properties?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/hubspot-web/src/trackCustomBehavioralEvent/index.ts b/packages/browser-destinations/destinations/hubspot-web/src/trackCustomBehavioralEvent/index.ts deleted file mode 100644 index 053501512f..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/trackCustomBehavioralEvent/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { Hubspot } from '../types' -import { flatten } from '../utils/flatten' - -// Change from unknown to the partner SDK types -const action: BrowserActionDefinition = { - title: 'Track Custom Behavioral Event', - description: 'Send a custom behavioral event to HubSpot.', - platform: 'web', - defaultSubscription: 'type = "track"', - fields: { - name: { - description: 'The internal event name assigned by HubSpot. This can be found in your HubSpot account. If the "Format Custom Behavioral Event Names" setting is enabled, Segment will automatically convert your Segment event name into the expected HubSpot internal event name format.', - label: 'Event Name', - type: 'string', - required: true, - default: { - '@path': '$.event' - } - }, - properties: { - description: 'A list of key-value pairs that describe the event.', - label: 'Event Properties', - type: 'object', - required: false, - default: { - '@path': '$.properties' - } - } - }, - perform: (_hsq, event) => { - let { name, properties } = event.payload - - if (event.settings.formatCustomBehavioralEventNames) { - name = `pe${event.settings.portalId}_${name.replace(/[\s.]+/g, '_').toLocaleLowerCase()}` - } - - // for custom properties, we will: - // remove any non-primitives, replace spaces and dots with underscores, then lowercase - properties = properties && flatten(properties, '', [], (key) => key.replace(/[\s.]+/g, '_').toLocaleLowerCase()) - - _hsq.push(['trackCustomBehavioralEvent', { name, properties }]) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/hubspot-web/src/trackPageView/__tests__/index.test.ts b/packages/browser-destinations/destinations/hubspot-web/src/trackPageView/__tests__/index.test.ts deleted file mode 100644 index 9f6969bfdd..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/trackPageView/__tests__/index.test.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime' -import hubspotDestination, { destination } from '../../index' -import { Hubspot } from '../../types' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'trackPageView', - name: 'Track Page View', - enabled: true, - subscribe: 'type = "page"', - mapping: { - path: { - '@path': '$.context.page.path' - } - } - } -] - -describe('Hubspot.trackPageView', () => { - const settings = { - portalId: '1234' - } - - let mockHubspot: Hubspot - let trackPageViewEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackPageViewEventPlugin] = await hubspotDestination({ - ...settings, - subscriptions - }) - trackPageViewEvent = trackPageViewEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockHubspot = { - push: jest.fn() - } - return Promise.resolve(mockHubspot) - }) - await trackPageViewEvent.load(Context.system(), {} as Analytics) - }) - - test('call both trackPageView and setPath', async () => { - const context = new Context({ - type: 'page', - name: 'Fried Chicken 🍗', - category: 'Chicken Shop', - context: { - page: { - path: '/fried-chicken' - } - } - }) - await trackPageViewEvent.track?.(context) - expect(mockHubspot.push).toHaveBeenCalledTimes(2) - expect(mockHubspot.push).toHaveBeenCalledWith(['trackPageView']) - expect(mockHubspot.push).toHaveBeenCalledWith(['setPath', '/fried-chicken']) - }) - - test('only calls trackPageView if no path is provided', async () => { - const context = new Context({ - type: 'page', - name: 'Spicy Chicken Sandwich 🌶', - category: 'Chicken Shop' - }) - await trackPageViewEvent.track?.(context) - expect(mockHubspot.push).toHaveBeenCalledTimes(1) - expect(mockHubspot.push).toHaveBeenCalledWith(['trackPageView']) - }) -}) diff --git a/packages/browser-destinations/destinations/hubspot-web/src/trackPageView/generated-types.ts b/packages/browser-destinations/destinations/hubspot-web/src/trackPageView/generated-types.ts deleted file mode 100644 index 73a0f8b707..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/trackPageView/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The path of the current page. The set path will be treated as relative to the current domain being viewed. - */ - path?: string -} diff --git a/packages/browser-destinations/destinations/hubspot-web/src/trackPageView/index.ts b/packages/browser-destinations/destinations/hubspot-web/src/trackPageView/index.ts deleted file mode 100644 index d506f37f27..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/trackPageView/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import { Hubspot } from '../types' -import type { Payload } from './generated-types' - -const action: BrowserActionDefinition = { - title: 'Track Page View', - description: 'Track the page view for the current page in HubSpot.', - defaultSubscription: 'type = "page"', - platform: 'web', - fields: { - path: { - description: - 'The path of the current page. The set path will be treated as relative to the current domain being viewed.', - label: 'Path String', - type: 'string', - required: false - } - }, - perform: (_hsq, event) => { - if (event.payload.path) { - _hsq.push(['setPath', event.payload.path]) - } - _hsq.push(['trackPageView']) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/hubspot-web/src/types.ts b/packages/browser-destinations/destinations/hubspot-web/src/types.ts deleted file mode 100644 index 97be6e4a72..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type Hubspot = { - push: (event: unknown[]) => void -} diff --git a/packages/browser-destinations/destinations/hubspot-web/src/upsertContact/__tests__/index.test.ts b/packages/browser-destinations/destinations/hubspot-web/src/upsertContact/__tests__/index.test.ts deleted file mode 100644 index 9aea19304f..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/upsertContact/__tests__/index.test.ts +++ /dev/null @@ -1,207 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime' -import hubspotDestination, { destination } from '../../index' -import { Hubspot } from '../../types' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'upsertContact', - name: 'Upsert Contact', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - email: { - '@path': '$.traits.email' - }, - custom_properties: { - '@path': '$.traits' - }, - id: { - '@path': '$.userId' - }, - company: { - '@path': '$.traits.company.name' - }, - country: { - '@path': '$.traits.address.country' - }, - state: { - '@path': '$.traits.address.state' - }, - city: { - '@path': '$.traits.address.city' - }, - address: { - '@path': '$.traits.address.street' - }, - zip: { - '@path': '$.traits.address.postalCode' - } - } - } -] - -describe('Hubspot.upsertContact', () => { - const settings = { - portalId: '1234', - formatCustomBehavioralEventNames: true - } - - let mockHubspot: Hubspot - let upsertContactEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [upsertContactEventPlugin] = await hubspotDestination({ - ...settings, - subscriptions - }) - upsertContactEvent = upsertContactEventPlugin - - jest.spyOn(destination, 'initialize').mockImplementation(() => { - mockHubspot = { - push: jest.fn() - } - return Promise.resolve(mockHubspot) - }) - await upsertContactEvent.load(Context.system(), {} as Analytics) - }) - - test('does not call Hubspot if there is no email', async () => { - const context = new Context({ - type: 'identify', - userId: '👻', - traits: { - friendly: true - } - }) - - await upsertContactEvent.identify?.(context) - expect(mockHubspot.push).toHaveBeenCalledTimes(0) - }) - - test('Identifies the user to Hubspot when email is present', async () => { - const context = new Context({ - type: 'identify', - userId: 'real_hubspot_tester', - traits: { - friendly: false, - email: 'real_hubspot_tester@jest_experts.com' - } - }) - - await upsertContactEvent.identify?.(context) - expect(mockHubspot.push).toHaveBeenCalledTimes(1) - expect(mockHubspot.push).toHaveBeenCalledWith([ - 'identify', - { email: 'real_hubspot_tester@jest_experts.com', id: 'real_hubspot_tester', friendly: false } - ]) - }) - - test('populates company info from the traits', async () => { - const context = new Context({ - type: 'identify', - userId: 'mike', - traits: { - friendly: false, - email: 'mike_eh@lph.com', - company: { - id: '123', - name: 'Los Pollos Hermanos', - industry: 'Transportation', - employee_count: 128, - plan: 'startup' - } - } - }) - - await upsertContactEvent.identify?.(context) - expect(mockHubspot.push).toHaveBeenCalledTimes(1) - expect(mockHubspot.push).toHaveBeenCalledWith([ - 'identify', - { email: 'mike_eh@lph.com', id: 'mike', friendly: false, company: 'Los Pollos Hermanos' } - ]) - }) - - test('populates address info from the traits', async () => { - const context = new Context({ - type: 'identify', - userId: 'mike', - traits: { - friendly: false, - email: 'mike_eh@lph.com', - address: { - street: '6th St', - city: 'San Francisco', - state: 'CA', - postalCode: '94103', - country: 'USA' - } - } - }) - - await upsertContactEvent.identify?.(context) - expect(mockHubspot.push).toHaveBeenCalledTimes(1) - expect(mockHubspot.push).toHaveBeenCalledWith([ - 'identify', - { - email: 'mike_eh@lph.com', - id: 'mike', - friendly: false, - address: '6th St', - country: 'USA', - state: 'CA', - city: 'San Francisco', - zip: '94103' - } - ]) - }) - - test('flattens nested traits', async () => { - const context = new Context({ - type: 'identify', - userId: 'mike', - traits: { - friendly: false, - email: 'mike_eh@lph.com', - address: { - street: '6th St', - city: 'San Francisco', - state: 'CA', - postalCode: '94103', - country: 'USA' - }, - equipment: { - type: '🚘', - color: 'red', - make: { - make: 'Tesla', - model: 'Model S', - year: 2019 - } - } - } - }) - - await upsertContactEvent.identify?.(context) - expect(mockHubspot.push).toHaveBeenCalledTimes(1) - expect(mockHubspot.push).toHaveBeenCalledWith([ - 'identify', - { - email: 'mike_eh@lph.com', - id: 'mike', - friendly: false, - address: '6th St', - country: 'USA', - state: 'CA', - city: 'San Francisco', - zip: '94103', - equipment_type: '🚘', - equipment_color: 'red', - equipment_make_make: 'Tesla', - equipment_make_model: 'Model S', - equipment_make_year: 2019 - } - ]) - }) -}) diff --git a/packages/browser-destinations/destinations/hubspot-web/src/upsertContact/generated-types.ts b/packages/browser-destinations/destinations/hubspot-web/src/upsertContact/generated-types.ts deleted file mode 100644 index 5ca1bc6c91..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/upsertContact/generated-types.ts +++ /dev/null @@ -1,42 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The contact’s email. Email is used to uniquely identify contact records in HubSpot and create or update the contact accordingly. - */ - email: string - /** - * A custom external ID that identifies the visitor. - */ - id?: string - /** - * A list of key-value pairs that describe the contact. Please see [HubSpot`s documentation](https://knowledge.hubspot.com/account/prevent-contact-properties-update-through-tracking-code-api) for limitations in updating contact properties. - */ - custom_properties?: { - [k: string]: unknown - } - /** - * The name of the company the contact is associated with. - */ - company?: string - /** - * The name of the country the contact is associated with. - */ - country?: string - /** - * The name of the state the contact is associated with. - */ - state?: string - /** - * The name of the city the contact is associated with. - */ - city?: string - /** - * The street address of the contact. - */ - address?: string - /** - * The postal code of the contact. - */ - zip?: string -} diff --git a/packages/browser-destinations/destinations/hubspot-web/src/upsertContact/index.ts b/packages/browser-destinations/destinations/hubspot-web/src/upsertContact/index.ts deleted file mode 100644 index 123c0b050f..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/upsertContact/index.ts +++ /dev/null @@ -1,121 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { Hubspot } from '../types' -import { flatten } from '../utils/flatten' - -const action: BrowserActionDefinition = { - title: 'Upsert Contact', - description: 'Create or update a contact in HubSpot.', - defaultSubscription: 'type = "identify"', - platform: 'web', - fields: { - email: { - description: - 'The contact’s email. Email is used to uniquely identify contact records in HubSpot and create or update the contact accordingly.', - label: 'Email Address', - type: 'string', - required: true, - default: { - '@path': '$.traits.email' - } - }, - id: { - description: 'A custom external ID that identifies the visitor.', - label: 'External ID', - type: 'string', - required: false, - default: { - '@path': '$.userId' - } - }, - custom_properties: { - description: 'A list of key-value pairs that describe the contact. Please see [HubSpot`s documentation](https://knowledge.hubspot.com/account/prevent-contact-properties-update-through-tracking-code-api) for limitations in updating contact properties.', - label: 'Custom Properties', - type: 'object', - required: false, - default: { - '@path': '$.traits' - } - }, - company: { - description: 'The name of the company the contact is associated with.', - label: 'Company Name', - type: 'string', - required: false, - default: { - '@path': '$.traits.company.name' - } - }, - country: { - description: 'The name of the country the contact is associated with.', - label: 'Country', - type: 'string', - required: false, - default: { - '@path': '$.traits.address.country' - } - }, - state: { - description: 'The name of the state the contact is associated with.', - label: 'State', - type: 'string', - required: false, - default: { - '@path': '$.traits.address.state' - } - }, - city: { - description: 'The name of the city the contact is associated with.', - label: 'City', - type: 'string', - required: false, - default: { - '@path': '$.traits.address.city' - } - }, - address: { - description: 'The street address of the contact.', - label: 'Street Address', - type: 'string', - required: false, - default: { - '@path': '$.traits.address.street' - } - }, - zip: { - description: 'The postal code of the contact.', - label: 'Postal Code', - type: 'string', - required: false, - default: { - '@if': { - exists: { '@path': '$.traits.address.postalCode' }, - then: { '@path': '$.traits.address.postalCode' }, - else: { '@path': '$.traits.address.postal_code' } - } - } - } - }, - perform: (_hsq, event) => { - const payload = event.payload - if (!payload.email) { - return - } - - // custom properties should be key-value pairs of strings, therefore, filtering out any non-primitive - const { custom_properties, ...rest } = payload - let flattenProperties - if (custom_properties) { - flattenProperties = flatten(custom_properties, '', ['address', 'company']) - } - - _hsq.push(['identify', { ...flattenProperties, ...rest }]) - - if (event.settings.flushIdentifyImmediately) { - _hsq.push(['trackPageView']) - } - } -} - -export default action diff --git a/packages/browser-destinations/destinations/hubspot-web/src/utils/flatten.ts b/packages/browser-destinations/destinations/hubspot-web/src/utils/flatten.ts deleted file mode 100644 index 6d1c8b53f6..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/src/utils/flatten.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { JSONPrimitive } from '@segment/actions-core' - -export type Properties = { - [k: string]: unknown -} - -type FlattenProperties = object & { - [k: string]: JSONPrimitive -} - -export function flatten( - data: Properties, - prefix = '', - skipList: string[] = [], - keyTransformation = (input: string) => input -): FlattenProperties { - let result: FlattenProperties = {} - for (const key in data) { - // skips flattening specific keys on the top level - if (!prefix && skipList.includes(key)) continue - - if (typeof data[key] === 'object' && data[key] !== null) { - const flattened = flatten(data[key] as Properties, `${prefix}_${key}`, skipList, keyTransformation) - result = { ...result, ...flattened } - } else { - result[keyTransformation(`${prefix}_${key}`.replace(/^_/, ''))] = data[key] as JSONPrimitive - } - } - return result -} diff --git a/packages/browser-destinations/destinations/hubspot-web/tsconfig.json b/packages/browser-destinations/destinations/hubspot-web/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/hubspot-web/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/intercom/package.json b/packages/browser-destinations/destinations/intercom/package.json deleted file mode 100644 index f79648cb1e..0000000000 --- a/packages/browser-destinations/destinations/intercom/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-intercom", - "version": "1.50.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/actions-core": "^3.116.0", - "@segment/actions-shared": "^1.98.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/intercom/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/intercom/src/__tests__/index.test.ts deleted file mode 100644 index a43b08bf86..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/__tests__/index.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import intercomDestination, { destination } from '../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'trackEvent', - name: 'Show', - enabled: true, - subscribe: 'type = "track"', - mapping: { - event_name: { - '@path': '$.event' - }, - event_metadata: { - '@path': '$.properties' - }, - revenue: { - '@path': '$.properties.revenue' - }, - currency: { - '@path': '$.properties.currency' - } - } - } -] - -describe('Intercom (actions)', () => { - test('loads Intercom with just appID', async () => { - const [event] = await intercomDestination({ - appId: 'topSecretKey', - richLinkProperties: ['article'], - activator: '#test', - subscriptions - }) - - jest.spyOn(destination, 'initialize') - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - expect(window.intercomSettings).toBeDefined() - expect(window.intercomSettings.app_id).toEqual('topSecretKey') - expect(window.intercomSettings.installation_type).toEqual('s') - - const scripts = window.document.querySelectorAll('script') - expect(scripts).toMatchInlineSnapshot(` - NodeList [ - , - ] - `) - }) -}) diff --git a/packages/browser-destinations/destinations/intercom/src/__tests__/utils.test.ts b/packages/browser-destinations/destinations/intercom/src/__tests__/utils.test.ts deleted file mode 100644 index 0d5547b548..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/__tests__/utils.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import dayjs from 'dayjs' -import { convertDateToUnix, filterCustomTraits, getWidgetOptions, isEmpty } from '../utils' - -describe('Utils test', () => { - describe('date handling tests', () => { - test('handles ISO datestrings', () => { - const date = new Date() - const isoDate = date.toISOString() - const unixDate = dayjs(isoDate).unix() - - expect(convertDateToUnix(isoDate)).toEqual(unixDate) - }) - - test('accepts Unix timestamps in seconds', () => { - const date = Math.floor(new Date().getTime() / 1000) - - expect(convertDateToUnix(date)).toEqual(date) - }) - - test('accepts Unix timestamps in milliseconds', () => { - const dateInMS = Math.floor(new Date().getTime()) - const dateInS = Math.floor(dateInMS / 1000) - - expect(convertDateToUnix(dateInMS)).toEqual(dateInS) - }) - }) - - describe('custom trait filtering tests', () => { - test('objects & arrays will be filtered out of traits', () => { - const traits = { - name: 'ibum', - badObj: { - badKey: 'badValue' - }, - badArray: ['i will be dropped'] - } - - expect(filterCustomTraits(traits)).toEqual({ - name: 'ibum' - }) - }) - - test('custom traits will be filtered with undefined traits object', () => { - const traits = undefined - expect(filterCustomTraits(traits)).toEqual({}) - }) - }) - - describe('isEmpty tests', () => { - test('isEmpty returns true if object is empty', () => { - const obj = {} - expect(isEmpty(obj)).toBe(true) - }) - - test('isEmpty returns false if object is not empty', () => { - const obj = { prop: 'value' } - expect(isEmpty(obj)).toBe(false) - }) - - test('isEmpty works for undefined obj', () => { - const obj = undefined - expect(isEmpty(obj)).toBe(true) - }) - }) - - describe('widget options tests', () => { - test('attaches `activator` if activator is not default', () => { - const activator = '#my-widget' - const hide_default_launcher = undefined - - expect(getWidgetOptions(hide_default_launcher, activator)).toEqual({ - widget: { - activator: activator - } - }) - }) - - test('attaches `hide_default_launcher` if its not undefined ', () => { - const activator = '#my-widget' - const hide_default_launcher = false - - expect(getWidgetOptions(hide_default_launcher, activator)).toEqual({ - widget: { - activator: activator - }, - hide_default_launcher: false - }) - }) - }) -}) diff --git a/packages/browser-destinations/destinations/intercom/src/api.ts b/packages/browser-destinations/destinations/intercom/src/api.ts deleted file mode 100644 index 01b9b307e6..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/api.ts +++ /dev/null @@ -1,11 +0,0 @@ -type method = 'trackEvent' | 'update' - -type IntercomApi = { - richLinkProperties: string[] | undefined - appId: string - activator: string | undefined -} - -type IntercomFunction = (method: method, ...args: unknown[]) => void - -export type Intercom = IntercomFunction & IntercomApi diff --git a/packages/browser-destinations/destinations/intercom/src/generated-types.ts b/packages/browser-destinations/destinations/intercom/src/generated-types.ts deleted file mode 100644 index d3b8f85611..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/generated-types.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * The app_id of your Intercom app which will indicate where to store any data. - */ - appId: string - /** - * By default, Intercom will inject their own inbox button onto the page, but you can choose to use your own custom button instead by providing a CSS selector, e.g. #my-button. You must have the "Show the Intercom Inbox" setting enabled for this to work. The default value is #IntercomDefaultWidget. - */ - activator?: string - /** - * A list of rich link property keys. - */ - richLinkProperties?: string[] - /** - * The regional API to use for processing the data - */ - apiBase?: string -} diff --git a/packages/browser-destinations/destinations/intercom/src/identifyCompany/__tests__/index.test.ts b/packages/browser-destinations/destinations/intercom/src/identifyCompany/__tests__/index.test.ts deleted file mode 100644 index d975260697..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/identifyCompany/__tests__/index.test.ts +++ /dev/null @@ -1,308 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime' -import intercomDestination, { destination } from '../../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'identifyCompany', - name: 'Show', - enabled: true, - subscribe: 'type = "group"', - mapping: { - company: { - company_id: { '@path': '$.groupId' }, - company_custom_traits: { - city: { - '@path': '$.traits.city' - }, - tech: { - '@path': '$.traits.tech' - } - }, - name: { '@path': '$.traits.name' }, - plan: { '@path': '$.traits.plan' }, - monthly_spend: { '@path': '$.traits.monthlySpend' }, - created_at: { - '@if': { - exists: { '@path': '$.traits.createdAt' }, - then: { '@path': '$.traits.createdAt' }, - else: { '@path': '$.traits.created_at' } - } - }, - size: { '@path': '$.traits.size' }, - website: { '@path': '$.traits.website' }, - industry: { '@path': '$.traits.industry' } - }, - hide_default_launcher: { - '@if': { - exists: { '@path': '$.context.Intercom.hideDefaultLauncher' }, - then: { '@path': '$.context.Intercom.hideDefaultLauncher' }, - else: { '@path': '$.context.Intercom.hide_default_launcher' } - } - } - } - } -] - -describe('Intercom.update (Company)', () => { - const settings = { - appId: 'superSecretAppID', - activator: '#IntercomDefaultWidget' - } - - let mockIntercom: jest.Mock - let identifyCompany: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [identifyCompanyPlugin] = await intercomDestination({ - ...settings, - subscriptions - }) - identifyCompany = identifyCompanyPlugin - - mockIntercom = jest.fn() - jest.spyOn(destination, 'initialize').mockImplementation(() => { - const mockedWithProps = Object.assign(mockIntercom as any, settings) - return Promise.resolve(mockedWithProps) - }) - await identifyCompany.load(Context.system(), {} as Analytics) - }) - - test('sends an id', async () => { - const context = new Context({ - type: 'group', - groupId: 'id' - }) - - await identifyCompany.group?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id' - } - }) - }) - - test('sends an id & properties', async () => { - const context = new Context({ - type: 'group', - groupId: 'id', - traits: { - name: 'Jeff' - } - }) - - await identifyCompany.group?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id', - name: 'Jeff' - } - }) - }) - - test('converts created_at from ISO-8601 to Unix', async () => { - const context = new Context({ - type: 'group', - groupId: 'id', - traits: { - createdAt: '2018-01-23T22:28:55.111Z' - } - }) - - await identifyCompany.group?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id', - created_at: 1516746535 - } - }) - }) - - test('maps created_at properly regardless of it being sent in snake_case or camelCase', async () => { - const context = new Context({ - type: 'group', - groupId: 'id', - traits: { - created_at: '2018-01-23T22:28:55.111Z' - } - }) - - await identifyCompany.group?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id', - created_at: 1516746535 - } - }) - }) - - test('sends custom traits', async () => { - const context = new Context({ - type: 'group', - groupId: 'id', - traits: { - wave: 'Capitola', - city: 'SF', - tech: true - } - }) - - await identifyCompany.group?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id', - city: 'SF', - tech: true - } - }) - }) - - test('drops arrays or objects in traits', async () => { - const context = new Context({ - type: 'group', - groupId: 'id', - traits: { - badArray: ['i', 'shall', 'be', 'dropped'], - badObject: { - rip: 'i will cease to exist' - }, - city: 'Belmar' - } - }) - - await identifyCompany.group?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id', - city: 'Belmar' - } - }) - }) - - test('should set hide_default_launcher if the setting is there', async () => { - const context = new Context({ - type: 'group', - groupId: 'id', - traits: { - name: 'Segment' - }, - context: { - Intercom: { - hideDefaultLauncher: true - } - } - }) - - await identifyCompany.group?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id', - name: 'Segment' - }, - hide_default_launcher: true - }) - }) -}) - -describe('Intercom.update (user) widget options', () => { - const settings = { - appId: 'superSecretAppID', - activator: '#customWidget' - } - - let mockIntercom: jest.Mock - let identifyCompany: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [identifyCompanyPlugin] = await intercomDestination({ - ...settings, - subscriptions - }) - identifyCompany = identifyCompanyPlugin - - mockIntercom = jest.fn() - jest.spyOn(destination, 'initialize').mockImplementation(() => { - const mockedWithProps = Object.assign(mockIntercom as any, settings) - return Promise.resolve(mockedWithProps) - }) - await identifyCompany.load(Context.system(), {} as Analytics) - }) - - test('sets activator if activator is not #IntercomDefaultWidget', async () => { - const context = new Context({ - type: 'group', - groupId: 'id', - traits: {} - }) - - await identifyCompany.group?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id' - }, - widget: { - activator: '#customWidget' - } - }) - }) - - test('should set hide_default_launcher if the setting is there', async () => { - const context = new Context({ - type: 'group', - groupId: 'id', - traits: {}, - context: { - Intercom: { - hideDefaultLauncher: false - } - } - }) - - await identifyCompany.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id' - }, - hide_default_launcher: false, - widget: { - activator: '#customWidget' - } - }) - }) - - test('maps hide_default_launcher correctly regardless of it being sent in snake_case or camelCase', async () => { - const context = new Context({ - type: 'group', - groupId: 'id', - traits: {}, - context: { - Intercom: { - hideDefaultLauncher: false - } - } - }) - - await identifyCompany.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - company: { - company_id: 'id' - }, - hide_default_launcher: false, - widget: { - activator: '#customWidget' - } - }) - }) -}) diff --git a/packages/browser-destinations/destinations/intercom/src/identifyCompany/generated-types.ts b/packages/browser-destinations/destinations/intercom/src/identifyCompany/generated-types.ts deleted file mode 100644 index 8790365dd7..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/identifyCompany/generated-types.ts +++ /dev/null @@ -1,51 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The user's company. - */ - company: { - /** - * The unique identifier of the company. - */ - company_id: string - /** - * The name of the company. - */ - name: string - /** - * The time the company was created in your system. - */ - created_at?: string | number - /** - * The name of the plan you have associated with the company. - */ - plan?: string - /** - * The monthly spend of the company, e.g. how much revenue the company generates for your business. - */ - monthly_spend?: number - /** - * The number of employees in the company. - */ - size?: number - /** - * The URL for the company website. - */ - website?: string - /** - * The industry that the company operates in. - */ - industry?: string - /** - * The custom attributes for the company object. - */ - company_custom_traits?: { - [k: string]: unknown - } - } - /** - * Selectively show the chat widget. As per [Intercom docs](https://www.intercom.com/help/en/articles/189-turn-off-show-or-hide-the-intercom-messenger), you want to first hide the Messenger for all users inside the Intercom UI using Messenger settings. Then think about how you want to programmatically decide which users you would like to show the widget to. - */ - hide_default_launcher?: boolean -} diff --git a/packages/browser-destinations/destinations/intercom/src/identifyCompany/index.ts b/packages/browser-destinations/destinations/intercom/src/identifyCompany/index.ts deleted file mode 100644 index 9afaf91ae9..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/identifyCompany/index.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { InputField } from '@segment/actions-core' -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import { Intercom } from '../api' -import type { Settings } from '../generated-types' -import { getCompanyProperties } from '../sharedCompanyProperties' -import { convertDateToUnix, filterCustomTraits, getWidgetOptions } from '../utils' -import type { Payload } from './generated-types' - -const companyProperties: Record = getCompanyProperties() - -const action: BrowserActionDefinition = { - title: 'Identify Company', - description: 'Create or update a company in Intercom.', - defaultSubscription: 'type = "group"', - platform: 'web', - fields: { - company: { - description: "The user's company.", - label: 'Company', - type: 'object', - required: true, - properties: companyProperties, - default: { - company_id: { '@path': '$.groupId' }, - name: { '@path': '$.traits.name' }, - created_at: { - '@if': { - exists: { '@path': '$.traits.createdAt' }, - then: { '@path': '$.traits.createdAt' }, - else: { '@path': '$.traits.created_at' } - } - }, - plan: { '@path': '$.traits.plan' }, - size: { '@path': '$.traits.size' }, - website: { '@path': '$.traits.website' }, - industry: { '@path': '$.traits.industry' }, - monthly_spend: { '@path': '$.traits.monthly_spend' } - } - }, - hide_default_launcher: { - description: - 'Selectively show the chat widget. As per [Intercom docs](https://www.intercom.com/help/en/articles/189-turn-off-show-or-hide-the-intercom-messenger), you want to first hide the Messenger for all users inside the Intercom UI using Messenger settings. Then think about how you want to programmatically decide which users you would like to show the widget to.', - label: 'Hide Default Launcher', - type: 'boolean', - required: false, - default: { - '@if': { - exists: { '@path': '$.context.Intercom.hideDefaultLauncher' }, - then: { '@path': '$.context.Intercom.hideDefaultLauncher' }, - else: { '@path': '$.context.Intercom.hide_default_launcher' } - } - } - } - }, - perform: (Intercom, event) => { - // remove properties that require extra handling - const { company_custom_traits, ...rest } = event.payload.company - let company = { ...rest } - - // convert date from ISO-8601 to UNIX - if (company?.created_at) { - company.created_at = convertDateToUnix(company.created_at) - } - - // drop custom objects & arrays - const filteredCustomTraits = filterCustomTraits(company_custom_traits) - - // merge filtered custom traits back into company object - company = { ...company, ...filteredCustomTraits } - - // get user's widget options - const widgetOptions = getWidgetOptions(event.payload.hide_default_launcher, Intercom.activator) - - //API call - Intercom('update', { - company, - ...widgetOptions - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/intercom/src/identifyUser/__tests__/index.test.ts b/packages/browser-destinations/destinations/intercom/src/identifyUser/__tests__/index.test.ts deleted file mode 100644 index 712f6e17c7..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/identifyUser/__tests__/index.test.ts +++ /dev/null @@ -1,460 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime' -import intercomDestination, { destination } from '../../index' -import { convertDateToUnix } from '../../utils' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'identifyUser', - name: 'Show', - enabled: true, - subscribe: 'type = "identify" or "page"', - mapping: { - user_id: { '@path': '$.userId' }, - custom_traits: { - major: { - '@path': '$.traits.major' - }, - school: { - '@path': '$.traits.school' - } - }, - name: { '@path': '$.traits.name' }, - email: { '@path': '$.traits.email' }, - phone: { '@path': '$.traits.phone' }, - unsubscribed_from_emails: { '@path': '$.traits.unsubscribedFromEmails' }, - created_at: { - '@if': { - exists: { '@path': '$.traits.createdAt' }, - then: { '@path': '$.traits.createdAt' }, - else: { '@path': '$.traits.created_at' } - } - }, - language_override: { '@path': '$.traits.languageOverride' }, - user_hash: { - '@if': { - exists: { '@path': '$.context.Intercom.user_hash' }, - then: { '@path': '$.context.Intercom.user_hash' }, - else: { '@path': '$.context.Intercom.userHash' } - } - }, - hide_default_launcher: { - '@if': { - exists: { '@path': '$.context.Intercom.hideDefaultLauncher' }, - then: { '@path': '$.context.Intercom.hideDefaultLauncher' }, - else: { '@path': '$.context.Intercom.hide_default_launcher' } - } - }, - avatar_image_url: { '@path': '$.traits.avatar' }, - company: { - company_id: { '@path': '$.traits.company.id' }, - name: { '@path': '$.traits.company.name' }, - plan: { '@path': '$.traits.company.plan' }, - monthly_spend: { '@path': '$.traits.company.monthlySpend' }, - created_at: { - '@if': { - exists: { '@path': '$.traits.company.createdAt' }, - then: { '@path': '$.traits.company.createdAt' }, - else: { '@path': '$.traits.company.created_at' } - } - }, - size: { '@path': '$.traits.company.size' }, - website: { '@path': '$.traits.company.website' }, - industry: { '@path': '$.traits.company.industry' }, - company_custom_traits: { - city: { - '@path': '$.traits.company.city' - }, - tech: { - '@path': '$.traits.company.tech' - } - } - }, - companies: { - '@arrayPath': [ - '$.traits.companies', - { - company_id: { '@path': '$.id' }, - name: { '@path': '$.name' }, - plan: { '@path': '$.plan' }, - monthly_spend: { '@path': '$.monthlySpend' }, - created_at: { - '@if': { - exists: { '@path': '$.createdAt' }, - then: { '@path': '$.createdAt' }, - else: { '@path': '$.created_at' } - } - }, - size: { '@path': '$.size' }, - website: { '@path': '$.website' }, - industry: { '@path': '$.industry' }, - company_custom_traits: { - city: { - '@path': '$.city' - }, - tech: { - '@path': '$.tech' - } - } - } - ] - } - } - } -] - -describe('Intercom.update (user)', () => { - const settings = { - appId: 'superSecretAppID', - activator: '#IntercomDefaultWidget' - } - - let mockIntercom: jest.Mock - let identifyUser: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [identifyUserPlugin] = await intercomDestination({ - ...settings, - subscriptions - }) - identifyUser = identifyUserPlugin - - mockIntercom = jest.fn() - jest.spyOn(destination, 'initialize').mockImplementation(() => { - const mockedWithProps = Object.assign(mockIntercom as any, settings) - return Promise.resolve(mockedWithProps) - }) - await identifyUser.load(Context.system(), {} as Analytics) - }) - - test('sends an id and traits', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: { - email: 'italo@gmail.com' - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - email: 'italo@gmail.com' - }) - }) - - test('sends a user name', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: { - email: 'italo@gmail.com', - name: 'italo ferreira' - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - email: 'italo@gmail.com', - name: 'italo ferreira' - }) - }) - - test('sends custom traits', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: { - shortboarder: true, - major: 'cs' - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - major: 'cs' - }) - }) - - test('drops custom arrays or objects from traits ', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: { - phone: '0000000', - dropMe: ['i', 'will', 'be', 'dropped'], - objDrop: { - foo: 'bar' - }, - company: { - id: 'twilio', - dropMe: ['i', 'will', 'be', 'dropped'], - objDrop: { - foo: 'bar' - } - }, - companies: [ - { - id: 'segment', - dropMe: ['i', 'will', 'be', 'dropped'], - objDrop: { - foo: 'bar' - } - } - ] - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - phone: '0000000', - company: { - company_id: 'twilio' - }, - companies: [ - { - company_id: 'segment' - } - ] - }) - }) - - test('converts dates', async () => { - const date = new Date() - const isoDate = date.toISOString() - const unixDate = convertDateToUnix(isoDate) - - const context = new Context({ - type: 'identify', - userId: 'id', - traits: { - createdAt: isoDate, - company: { - id: 'twilio', - createdAt: isoDate - }, - companies: [ - { - id: 'segment', - createdAt: isoDate - } - ] - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - created_at: unixDate, - company: { - company_id: 'twilio', - created_at: unixDate - }, - companies: [ - { - company_id: 'segment', - created_at: unixDate - } - ] - }) - }) - - test('accepts camel/snake case for created_at', async () => { - const date = new Date() - const isoDate = date.toISOString() - const unixDate = convertDateToUnix(isoDate) - - const context = new Context({ - type: 'identify', - userId: 'id', - traits: { - created_at: isoDate, - company: { - id: 'twilio', - created_at: isoDate - }, - companies: [ - { - id: 'segment', - created_at: isoDate - } - ] - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - created_at: unixDate, - company: { - company_id: 'twilio', - created_at: unixDate - }, - companies: [ - { - company_id: 'segment', - created_at: unixDate - } - ] - }) - }) - - test('avatar works', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: { - avatar: 'someurl' - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - avatar: { - image_url: 'someurl', - type: 'avatar' - } - }) - }) - - test('allows passing a user hash', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: {}, - context: { - Intercom: { - user_hash: 'x' - } - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - user_hash: 'x' - }) - }) - - test('accepts snake/camel case for user_hash', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: {}, - context: { - Intercom: { - userHash: 'x' - } - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - user_hash: 'x' - }) - }) -}) - -describe('Intercom.update (user) widget options', () => { - const settings = { - appId: 'superSecretAppID', - activator: '#customWidget' - } - - let mockIntercom: jest.Mock - let identifyUser: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [identifyUserPlugin] = await intercomDestination({ - ...settings, - subscriptions - }) - identifyUser = identifyUserPlugin - - mockIntercom = jest.fn() - jest.spyOn(destination, 'initialize').mockImplementation(() => { - const mockedWithProps = Object.assign(mockIntercom as any, settings) - return Promise.resolve(mockedWithProps) - }) - await identifyUser.load(Context.system(), {} as Analytics) - }) - - test('sets activator if activator is not #IntercomDefaultWidget', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: {} - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - widget: { - activator: '#customWidget' - } - }) - }) - - test('should set hide_default_launcher if the setting is there', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: {}, - context: { - Intercom: { - hideDefaultLauncher: true - } - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - hide_default_launcher: true, - widget: { - activator: '#customWidget' - } - }) - }) - - test('accepts snake/camel case for hide_default_launcher', async () => { - const context = new Context({ - type: 'identify', - userId: 'id', - traits: {}, - context: { - Intercom: { - hide_default_launcher: true - } - } - }) - - await identifyUser.identify?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('update', { - user_id: 'id', - hide_default_launcher: true, - widget: { - activator: '#customWidget' - } - }) - }) -}) diff --git a/packages/browser-destinations/destinations/intercom/src/identifyUser/generated-types.ts b/packages/browser-destinations/destinations/intercom/src/identifyUser/generated-types.ts deleted file mode 100644 index e5e4bc4306..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/identifyUser/generated-types.ts +++ /dev/null @@ -1,136 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * A unique identifier for the user. - */ - user_id?: string - /** - * The user's custom attributes. - */ - custom_traits?: { - [k: string]: unknown - } - /** - * The user's name. - */ - name?: string - /** - * The user's phone number. - */ - phone?: string - /** - * The user's email unsubscribe status. - */ - unsubscribed_from_emails?: boolean - /** - * The user's messenger language (instead of relying on browser language settings). - */ - language_override?: string - /** - * The user's email address. - */ - email?: string - /** - * The time the user was created in your system. - */ - created_at?: string | number - /** - * The URL for the user's avatar/profile image. - */ - avatar_image_url?: string - /** - * The user hash used for identity verification. See [Intercom docs](https://www.intercom.com/help/en/articles/183-enable-identity-verification-for-web-and-mobile) for more information on how to set this field. - */ - user_hash?: string - /** - * The user's company. - */ - company?: { - /** - * The unique identifier of the company. - */ - company_id: string - /** - * The name of the company. - */ - name: string - /** - * The time the company was created in your system. - */ - created_at?: string | number - /** - * The name of the plan you have associated with the company. - */ - plan?: string - /** - * The monthly spend of the company, e.g. how much revenue the company generates for your business. - */ - monthly_spend?: number - /** - * The number of employees in the company. - */ - size?: number - /** - * The URL for the company website. - */ - website?: string - /** - * The industry that the company operates in. - */ - industry?: string - /** - * The custom attributes for the company object. - */ - company_custom_traits?: { - [k: string]: unknown - } - } - /** - * The array of companies the user is associated to. - */ - companies?: { - /** - * The unique identifier of the company. - */ - company_id: string - /** - * The name of the company. - */ - name: string - /** - * The time the company was created in your system. - */ - created_at?: string | number - /** - * The name of the plan you have associated with the company. - */ - plan?: string - /** - * The monthly spend of the company, e.g. how much revenue the company generates for your business. - */ - monthly_spend?: number - /** - * The number of employees in the company. - */ - size?: number - /** - * The URL for the company website. - */ - website?: string - /** - * The industry that the company operates in. - */ - industry?: string - /** - * The custom attributes for the company object. - */ - company_custom_traits?: { - [k: string]: unknown - } - }[] - /** - * Selectively show the chat widget. As per [Intercom docs](https://www.intercom.com/help/en/articles/189-turn-off-show-or-hide-the-intercom-messenger), you want to first hide the Messenger for all users inside the Intercom UI using Messenger settings. Then think about how you want to programmatically decide which users you would like to show the widget to. - */ - hide_default_launcher?: boolean -} diff --git a/packages/browser-destinations/destinations/intercom/src/identifyUser/index.ts b/packages/browser-destinations/destinations/intercom/src/identifyUser/index.ts deleted file mode 100644 index 4384859222..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/identifyUser/index.ts +++ /dev/null @@ -1,237 +0,0 @@ -import { InputField } from '@segment/actions-core' -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import { Intercom } from '../api' -import type { Settings } from '../generated-types' -import { getCompanyProperties } from '../sharedCompanyProperties' -import { convertDateToUnix, filterCustomTraits, getWidgetOptions, isEmpty } from '../utils' -import type { Payload } from './generated-types' - -const companyProperties: Record = getCompanyProperties() - -const action: BrowserActionDefinition = { - title: 'Identify User', - description: 'Create or update a user in Intercom.', - defaultSubscription: 'type = "identify" or type = "page"', - platform: 'web', - fields: { - user_id: { - description: 'A unique identifier for the user.', - label: 'User ID', - type: 'string', - required: false, - default: { - '@path': '$.userId' - } - }, - custom_traits: { - description: "The user's custom attributes.", - label: 'Custom Attributes', - type: 'object', - required: false, - defaultObjectUI: 'keyvalue' - }, - name: { - description: "The user's name.", - label: 'Name', - type: 'string', - required: false, - default: { - '@path': '$.traits.name' - } - }, - phone: { - description: "The user's phone number.", - label: 'Phone Number', - type: 'string', - required: false, - default: { - '@path': '$.traits.phone' - } - }, - unsubscribed_from_emails: { - description: "The user's email unsubscribe status.", - label: 'Unsubscribed From Emails', - type: 'boolean', - required: false - }, - language_override: { - description: "The user's messenger language (instead of relying on browser language settings).", - label: 'Language Override', - type: 'string', - required: false - }, - email: { - description: "The user's email address.", - label: 'Email Address', - type: 'string', - required: false, - default: { - '@path': '$.traits.email' - } - }, - created_at: { - description: 'The time the user was created in your system.', - label: 'User Creation Time', - type: 'datetime', - required: false, - default: { - '@if': { - exists: { '@path': '$.traits.createdAt' }, - then: { '@path': '$.traits.createdAt' }, - else: { '@path': '$.traits.created_at' } - } - } - }, - avatar_image_url: { - description: "The URL for the user's avatar/profile image.", - label: 'Avatar', - type: 'string', - required: false, - default: { '@path': '$.traits.avatar' } - }, - user_hash: { - description: - 'The user hash used for identity verification. See [Intercom docs](https://www.intercom.com/help/en/articles/183-enable-identity-verification-for-web-and-mobile) for more information on how to set this field.', - label: 'User Hash', - type: 'string', - required: false, - default: { - '@if': { - exists: { '@path': '$.integrations.Intercom.user_hash' }, - then: { '@path': '$.integrations.Intercom.user_hash' }, - else: { '@path': '$.integrations.Intercom.userHash' } - } - } - }, - company: { - description: "The user's company.", - label: 'Company', - type: 'object', - required: false, - properties: companyProperties, - default: { - company_id: { '@path': '$.traits.company.id' }, - name: { '@path': '$.traits.company.name' }, - created_at: { - '@if': { - exists: { '@path': '$.traits.company.createdAt' }, - then: { '@path': '$.traits.company.createdAt' }, - else: { '@path': '$.traits.company.created_at' } - } - }, - plan: { '@path': '$.traits.company.plan' }, - size: { '@path': '$.traits.company.size' }, - website: { '@path': '$.traits.company.website' }, - industry: { '@path': '$.traits.company.industry' }, - monthly_spend: { '@path': '$.traits.company.monthly_spend' } - } - }, - companies: { - description: 'The array of companies the user is associated to.', - label: 'Companies', - type: 'object', - multiple: true, - required: false, - properties: companyProperties, - default: { - '@arrayPath': [ - '$.traits.companies', - { - company_id: { '@path': '$.id' }, - name: { '@path': '$.name' }, - created_at: { - '@if': { - exists: { '@path': '$.createdAt' }, - then: { '@path': '$.createdAt' }, - else: { '@path': '$.created_at' } - } - }, - plan: { '@path': '$.plan' }, - size: { '@path': '$.size' }, - website: { '@path': '$.website' }, - industry: { '@path': '$.industry' }, - monthly_spend: { '@path': '$.monthly_spend' } - } - ] - } - }, - hide_default_launcher: { - description: - 'Selectively show the chat widget. As per [Intercom docs](https://www.intercom.com/help/en/articles/189-turn-off-show-or-hide-the-intercom-messenger), you want to first hide the Messenger for all users inside the Intercom UI using Messenger settings. Then think about how you want to programmatically decide which users you would like to show the widget to.', - label: 'Hide Default Launcher', - type: 'boolean', - required: false, - default: { - '@if': { - exists: { '@path': '$.context.Intercom.hideDefaultLauncher' }, - then: { '@path': '$.context.Intercom.hideDefaultLauncher' }, - else: { '@path': '$.context.Intercom.hide_default_launcher' } - } - } - } - }, - perform: (Intercom, event) => { - // remove properties that require extra handling - const { custom_traits, avatar_image_url, ...rest } = event.payload - const payload = { ...rest } - - // remove company if it is empty - if (isEmpty(payload.company?.company_custom_traits)) { - delete payload.company?.company_custom_traits - } - if (isEmpty(payload.company)) { - delete payload.company - } - - // convert 'created_at' date properties from ISO-8601 to UNIX - const companies = Array.isArray(payload.companies) ? [...payload.companies] : [] - const datesToConvert = [payload, payload.company, ...companies] - for (const objectWithDateProp of datesToConvert) { - if (objectWithDateProp && objectWithDateProp?.created_at) { - objectWithDateProp.created_at = convertDateToUnix(objectWithDateProp.created_at) - } - } - - // drop custom objects & arrays - const filteredCustomTraits = filterCustomTraits(custom_traits) - - // drop custom objects & arrays - if (payload.company) { - const { company_custom_traits, ...rest } = payload.company - const companyFilteredCustomTraits = filterCustomTraits(company_custom_traits) - payload.company = { ...rest, ...companyFilteredCustomTraits } - } - - // drop custom objects & arrays - if (payload.companies) { - payload.companies = payload.companies.map((company) => { - const { company_custom_traits, ...rest } = company - const companyFilteredCustomTraits = filterCustomTraits(company_custom_traits) - company = { ...rest, ...companyFilteredCustomTraits } - return company - }) - } - - // get user's widget options - const widgetOptions = getWidgetOptions(payload.hide_default_launcher, Intercom.activator) - - // create the avatar object - let avatar = {} - if (avatar_image_url) { - avatar = { - image_url: avatar_image_url, - type: 'avatar' - } - } - - // API call - Intercom('update', { - ...payload, - ...filteredCustomTraits, - ...widgetOptions, - ...(!isEmpty(avatar) && { avatar }) - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/intercom/src/index.ts b/packages/browser-destinations/destinations/intercom/src/index.ts deleted file mode 100644 index 598f003dda..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/index.ts +++ /dev/null @@ -1,117 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import { initialBoot, initScript, initSettings } from './init-script' - -import { Intercom } from './api' -import trackEvent from './trackEvent' -import identifyUser from './identifyUser' -import identifyCompany from './identifyCompany' -import { defaultValues } from '@segment/actions-core' - -declare global { - interface Window { - Intercom: Intercom - intercomSettings: { - app_id: string - installation_type?: string - } - } -} - -export const destination: BrowserDestinationDefinition = { - name: 'Intercom Web (Actions)', - slug: 'actions-intercom-web', - mode: 'device', - presets: [ - { - name: 'Track Event', - subscribe: 'type = "track"', - partnerAction: 'trackEvent', - mapping: defaultValues(trackEvent.fields), - type: 'automatic' - }, - { - name: 'Identify User', - subscribe: 'type = "identify" or type = "page"', - partnerAction: 'identifyUser', - mapping: defaultValues(identifyUser.fields), - type: 'automatic' - }, - { - name: 'Identify Company', - subscribe: 'type = "group"', - partnerAction: 'identifyCompany', - mapping: defaultValues(identifyCompany.fields), - type: 'automatic' - } - ], - settings: { - appId: { - description: 'The app_id of your Intercom app which will indicate where to store any data.', - label: 'App ID', - type: 'string', - required: true - }, - activator: { - description: - 'By default, Intercom will inject their own inbox button onto the page, but you can choose to use your own custom button instead by providing a CSS selector, e.g. #my-button. You must have the "Show the Intercom Inbox" setting enabled for this to work. The default value is #IntercomDefaultWidget.', - label: 'Custom Inbox Button Selector', - type: 'string', - required: false, - default: '#IntercomDefaultWidget' - }, - richLinkProperties: { - description: 'A list of rich link property keys.', - label: 'Rich Link Properties', - type: 'string', - multiple: true, - required: false - }, - apiBase: { - description: 'The regional API to use for processing the data', - label: 'Regional Data Hosting', - type: 'string', - choices: [ - { - label: 'US', - value: 'https://api-iam.intercom.io' - }, - { - label: 'EU', - value: 'https://api-iam.eu.intercom.io' - }, - { - label: 'Australia', - value: 'https://api-iam.au.intercom.io' - } - ], - default: 'https://api-iam.intercom.io', - required: false - } - }, - - initialize: async ({ settings }, deps) => { - //initialize Intercom - initScript({ appId: settings.appId }) - initSettings({ appId: settings.appId }) - const preloadedIntercom = window.Intercom - initialBoot(settings.appId, { api_base: settings.apiBase }) - - await deps.resolveWhen(() => window.Intercom !== preloadedIntercom, 100) - - window.Intercom.richLinkProperties = settings.richLinkProperties - window.Intercom.appId = settings.appId - window.Intercom.activator = settings.activator - - return window.Intercom - }, - - actions: { - trackEvent, - identifyUser, - identifyCompany - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/intercom/src/init-script.ts b/packages/browser-destinations/destinations/intercom/src/init-script.ts deleted file mode 100644 index b6b624276b..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/init-script.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck - -export function initScript({ appId }) { - //Set your APP_ID - var APP_ID = appId - ;(function () { - var w = window - var ic = w.Intercom - if (typeof ic === 'function') { - ic('reattach_activator') - ic('update', w.intercomSettings) - } else { - var d = document - var i = function () { - i.c(arguments) - } - i.q = [] - i.c = function (args) { - i.q.push(args) - } - w.Intercom = i - var l = function () { - var s = d.createElement('script') - s.type = 'text/javascript' - s.async = true - s.src = 'https://widget.intercom.io/widget/' + APP_ID - var x = d.getElementsByTagName('script')[0] - x.parentNode.insertBefore(s, x) - } - if (document.readyState === 'complete') { - l() - } else if (w.attachEvent) { - w.attachEvent('onload', l) - } else { - w.addEventListener('load', l, false) - } - } - })() -} - -export function initialBoot(appId: string, options = {}) { - window && - window.Intercom && - window.Intercom('boot', { - app_id: appId, - installation_type: 's', - ...options - }) -} - -export function initSettings({ appId }) { - if (window.intercomSettings) { - window.intercomSettings.app_id = appId - window.intercomSettings.installation_type = 's' - } else { - window.intercomSettings = { - app_id: appId, - installation_type: 's' - } - } -} diff --git a/packages/browser-destinations/destinations/intercom/src/sharedCompanyProperties.ts b/packages/browser-destinations/destinations/intercom/src/sharedCompanyProperties.ts deleted file mode 100644 index 13dd789b57..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/sharedCompanyProperties.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { InputField } from '@segment/actions-core' - -export const getCompanyProperties = (): Record => ({ - company_id: { - description: 'The unique identifier of the company.', - label: 'Company ID', - type: 'string', - required: true - }, - name: { - description: 'The name of the company.', - label: 'Company Name', - type: 'string', - required: true - }, - created_at: { - description: 'The time the company was created in your system.', - label: 'Company Creation Time', - type: 'datetime', - required: false - }, - plan: { - description: 'The name of the plan you have associated with the company.', - label: 'Company Plan', - type: 'string', - required: false - }, - monthly_spend: { - description: 'The monthly spend of the company, e.g. how much revenue the company generates for your business.', - label: 'Monthly Spend', - type: 'integer', - required: false - }, - size: { - description: 'The number of employees in the company.', - label: 'Company Size', - type: 'integer', - required: false - }, - website: { - description: 'The URL for the company website.', - label: 'Company Website', - type: 'string', - required: false - }, - industry: { - description: 'The industry that the company operates in.', - label: 'Industry', - type: 'string', - required: false - }, - company_custom_traits: { - description: 'The custom attributes for the company object.', - label: 'Company Custom Attributes', - type: 'object', - required: false, - defaultObjectUI: 'keyvalue' - } -}) diff --git a/packages/browser-destinations/destinations/intercom/src/trackEvent/__tests__/index.test.ts b/packages/browser-destinations/destinations/intercom/src/trackEvent/__tests__/index.test.ts deleted file mode 100644 index 7dc519c12b..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/trackEvent/__tests__/index.test.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import { Subscription } from '@segment/browser-destination-runtime' -import intercomDestination, { destination } from '../../index' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'trackEvent', - name: 'Show', - enabled: true, - subscribe: 'type = "track"', - mapping: { - event_name: { - '@path': '$.event' - }, - event_metadata: { - '@path': '$.properties' - }, - revenue: { - '@path': '$.properties.revenue' - }, - currency: { - '@path': '$.properties.currency' - } - } - } -] - -describe('Intercom.trackEvent', () => { - const settings = { - appId: 'superSecretAppID' - } - - let mockIntercom: jest.Mock - let trackEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await intercomDestination({ - ...settings, - subscriptions - }) - trackEvent = trackEventPlugin - - mockIntercom = jest.fn() - jest.spyOn(destination, 'initialize').mockImplementation(() => { - const mockedWithProps = Object.assign(mockIntercom as any, settings) - return Promise.resolve(mockedWithProps) - }) - await trackEvent.load(Context.system(), {} as Analytics) - }) - - test('maps custom traits correctly', async () => { - const context = new Context({ - type: 'track', - event: 'surfboard-bought', - properties: { - surfer: 'kelly slater' - } - }) - await trackEvent.track?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('trackEvent', 'surfboard-bought', { - surfer: 'kelly slater' - }) - }) - - test('maps price correctly', async () => { - const context = new Context({ - type: 'track', - event: 'surfboard-bought', - properties: { - revenue: 100, - currency: 'USD' - } - }) - await trackEvent.track?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('trackEvent', 'surfboard-bought', { - price: { - amount: 10000, - currency: 'USD' - } - }) - }) - - test('currency defaults to USD if omitted', async () => { - const context = new Context({ - type: 'track', - event: 'surfboard-bought', - properties: { - revenue: 100 - } - }) - await trackEvent.track?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('trackEvent', 'surfboard-bought', { - price: { - amount: 10000, - currency: 'USD' - } - }) - }) - - test('drops arrays or objects in properties', async () => { - const context = new Context({ - type: 'track', - event: 'surfboard-bought', - properties: { - surfer: 'kelly slater', - dropMe: { - foo: 'bar', - ahoy: { - okay: 'hello' - } - }, - arr: ['hi', 'sup', 'yo'] - } - }) - - await trackEvent.track?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('trackEvent', 'surfboard-bought', { - surfer: 'kelly slater' - }) - }) -}) - -describe('Intercom.trackEvent with rich link properties', () => { - const settings = { - appId: 'superSecretAppID', - richLinkProperties: ['article'] - } - - let mockIntercom: jest.Mock - let trackEvent: any - beforeEach(async () => { - jest.restoreAllMocks() - - const [trackEventPlugin] = await intercomDestination({ - ...settings, - subscriptions - }) - trackEvent = trackEventPlugin - - mockIntercom = jest.fn() - jest.spyOn(destination, 'initialize').mockImplementation(() => { - const mockedWithProps = Object.assign(mockIntercom as any, settings) - return Promise.resolve(mockedWithProps) - }) - await trackEvent.load(Context.system(), {} as Analytics) - }) - - test('rich link properties are permitted', async () => { - const context = new Context({ - type: 'track', - event: 'surfboard-bought', - properties: { - surfer: 'kelly slater', - dropMe: { - foo: 'bar' - }, - article: { - url: 'im a link', - value: 'hi' - } - } - }) - - await trackEvent.track?.(context) - - expect(mockIntercom).toHaveBeenCalledWith('trackEvent', 'surfboard-bought', { - surfer: 'kelly slater', - article: { - url: 'im a link', - value: 'hi' - } - }) - }) -}) diff --git a/packages/browser-destinations/destinations/intercom/src/trackEvent/generated-types.ts b/packages/browser-destinations/destinations/intercom/src/trackEvent/generated-types.ts deleted file mode 100644 index 3b3d0383fd..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/trackEvent/generated-types.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The name of the event. - */ - event_name: string - /** - * The amount associated with a purchase. Segment will multiply by 100 as Intercom requires the amount in cents. - */ - revenue?: number - /** - * The currency of the purchase amount. Segment will default to USD if revenue is provided without a currency. - */ - currency?: string - /** - * Optional metadata describing the event. - */ - event_metadata?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/intercom/src/trackEvent/index.ts b/packages/browser-destinations/destinations/intercom/src/trackEvent/index.ts deleted file mode 100644 index 51b805c026..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/trackEvent/index.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import { Intercom } from '../api' -import type { Settings } from '../generated-types' -import { filterCustomTraits, isEmpty } from '../utils' -import type { Payload } from './generated-types' - -const action: BrowserActionDefinition = { - title: 'Track Event', - description: 'Submit an event to Intercom.', - defaultSubscription: 'type = "track"', - platform: 'web', - fields: { - event_name: { - description: 'The name of the event.', - label: 'Event Name', - type: 'string', - required: true, - default: { - '@path': '$.event' - } - }, - revenue: { - description: - 'The amount associated with a purchase. Segment will multiply by 100 as Intercom requires the amount in cents.', - label: 'Revenue', - type: 'number', - required: false, - default: { - '@path': '$.properties.revenue' - } - }, - currency: { - description: - 'The currency of the purchase amount. Segment will default to USD if revenue is provided without a currency.', - label: 'Currency', - type: 'string', - required: false, - default: { - '@path': '$.properties.currency' - } - }, - event_metadata: { - description: 'Optional metadata describing the event.', - label: 'Event Metadata', - type: 'object', - required: false, - default: { - '@path': '$.properties' - } - } - }, - perform: (Intercom, event) => { - //remove event_name & event_metadata from the payload (they will be handled separately) - const { event_name, event_metadata, ...rest } = event.payload - const payload = { ...rest } - const richLinkProperties = Intercom.richLinkProperties ? Intercom.richLinkProperties : [] - - // create a list of the richLinkObjects that will be passed to Intercom - const richLinkObjects: { [k: string]: unknown } = {} - if (event_metadata && richLinkProperties.length != 0) { - Object.entries(event_metadata).forEach(([key, value]) => { - if (richLinkProperties.includes(key)) { - richLinkObjects[key] = value - } - }) - } - - // filter out reserved fields, drop custom objects & arrays - const filteredMetadata = filterCustomTraits(event_metadata) - - // create price object - let price = {} - if (payload.revenue) { - price = { - amount: payload.revenue * 100, - currency: payload.currency ?? 'USD' - } - delete filteredMetadata.revenue - delete filteredMetadata.currency - } - - //merge richLinkObjects into the final payload - //API call - Intercom('trackEvent', event_name, { - ...filteredMetadata, - ...richLinkObjects, - ...(!isEmpty(price) && { price }) - }) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/intercom/src/utils.ts b/packages/browser-destinations/destinations/intercom/src/utils.ts deleted file mode 100644 index d29e85ecde..0000000000 --- a/packages/browser-destinations/destinations/intercom/src/utils.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { isArray, isObject } from '@segment/actions-core' -import { isNonEmpty } from '@segment/actions-shared' -import dayjs from 'dayjs' - -export function convertDateToUnix(created_at: string | number): number { - if (typeof created_at === 'number') { - let unixDate = dayjs.unix(created_at).unix() - if (unixDate.toString().length == 13) { - unixDate = Math.floor(unixDate / 1000) - } - return unixDate - } - return dayjs(created_at).unix() -} - -export function filterCustomTraits(traits: { [k: string]: unknown } | undefined) { - const filteredCustomTraits: { [k: string]: unknown } = {} - if (traits) { - for (const [key, value] of Object.entries(traits)) { - if (!isArray(value) && !isObject(value)) { - filteredCustomTraits[key] = value - } - } - } - return filteredCustomTraits -} - -export function getWidgetOptions(hide_default_launcher: boolean | undefined, activator: string | undefined) { - const widgetOptions: { [key: string]: unknown } = {} - if (hide_default_launcher !== undefined) { - widgetOptions.hide_default_launcher = hide_default_launcher - } - if (activator !== '#IntercomDefaultWidget') { - widgetOptions.widget = { - activator: activator - } - } - return widgetOptions -} - -export function isEmpty(o: object | undefined) { - return !isNonEmpty(o) -} diff --git a/packages/browser-destinations/destinations/intercom/tsconfig.json b/packages/browser-destinations/destinations/intercom/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/intercom/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/iterate/package.json b/packages/browser-destinations/destinations/iterate/package.json deleted file mode 100644 index 5797c8fd6f..0000000000 --- a/packages/browser-destinations/destinations/iterate/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-iterate", - "version": "1.47.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/actions-core": "^3.116.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/iterate/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/iterate/src/__tests__/index.test.ts deleted file mode 100644 index 948fd33908..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/__tests__/index.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import iterateDestination, { destination } from '../index' -import { Subscription } from '@segment/browser-destination-runtime/types' - -const subscriptions: Subscription[] = [ - { - partnerAction: 'trackEvent', - name: 'Track Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - name: { - '@path': '$.name' - } - } - } -] - -describe('Iterate initialization', () => { - test('can load Iterate', async () => { - const [event] = await iterateDestination({ - apiKey: 'abc123', - subscriptions - }) - - jest.spyOn(destination.actions.trackEvent, 'perform') - jest.spyOn(destination, 'initialize') - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - - const ctx = await event.track?.( - new Context({ - type: 'track', - name: 'example-event' - }) - ) - - expect(destination.actions.trackEvent.perform).toHaveBeenCalled() - expect(ctx).not.toBeUndefined() - - const scripts = window.document.querySelectorAll('script') - scripts[0].src = scripts[0].src.replace(/match-prod-.*.js/, 'match-prod.js') - expect(scripts).toMatchInlineSnapshot(` - NodeList [ - , - ] - `) - }) -}) diff --git a/packages/browser-destinations/destinations/iterate/src/generated-types.ts b/packages/browser-destinations/destinations/iterate/src/generated-types.ts deleted file mode 100644 index fea6679841..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * The Embed API Key for your account. You can find this on your settings pages. - */ - apiKey: string -} diff --git a/packages/browser-destinations/destinations/iterate/src/identifyUser/__tests__/index.test.ts b/packages/browser-destinations/destinations/iterate/src/identifyUser/__tests__/index.test.ts deleted file mode 100644 index 190c7cab82..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/identifyUser/__tests__/index.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import iterateDestination, { destination } from '../../index' - -describe('Iterate.identifyUser', () => { - it('Should call identify', async () => { - const [identifyEvent] = await iterateDestination({ - apiKey: '123', - subscriptions: [ - { - partnerAction: 'identifyUser', - name: 'Identify User', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - userId: { - '@path': '$.userId' - }, - traits: { - '@path': '$.traits' - } - } - } - ] - }) - - destination.actions.identifyUser.perform = jest.fn() - const identifySpy = jest.spyOn(destination.actions.identifyUser, 'perform') - await identifyEvent.load(Context.system(), {} as Analytics) - - await identifyEvent.identify?.( - new Context({ - type: 'identify', - userId: '123abc', - traits: { - foo: 'bar' - } - }) - ) - - expect(identifySpy).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - userId: '123abc', - traits: { - foo: 'bar' - } - } - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/iterate/src/identifyUser/generated-types.ts b/packages/browser-destinations/destinations/iterate/src/identifyUser/generated-types.ts deleted file mode 100644 index d21285f3d9..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/identifyUser/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The user's identity. - */ - userId?: string - /** - * The Segment traits to be forwarded to Iterate. - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/iterate/src/identifyUser/index.ts b/packages/browser-destinations/destinations/iterate/src/identifyUser/index.ts deleted file mode 100644 index 5d02d16e19..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/identifyUser/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { Iterate as IterateClient, Command } from '../types' - -const action: BrowserActionDefinition = { - title: 'Identify User', - description: 'Sets user identity', - platform: 'web', - defaultSubscription: 'type = "identify"', - fields: { - userId: { - type: 'string', - required: false, - description: "The user's identity.", - label: 'Identity', - default: { - '@path': '$.userId' - } - }, - traits: { - type: 'object', - required: false, - description: 'The Segment traits to be forwarded to Iterate.', - label: 'Traits', - default: { - '@path': '$.traits' - } - } - }, - perform: (Iterate, event) => { - const traits = event.payload.traits || {} - - if (event.payload.userId) { - traits['external_id'] = event.payload.userId - } - - Iterate(Command.Identify, traits) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/iterate/src/index.ts b/packages/browser-destinations/destinations/iterate/src/index.ts deleted file mode 100644 index 310ba47b3e..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/index.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import type { Settings } from './generated-types' -import { Iterate, IterateApi, IterateSettings } from './types' -import { defaultValues } from '@segment/actions-core' - -import trackEvent from './trackEvent' -import identifyUser from './identifyUser' - -// Declare global to access your client -declare global { - interface Window { - Iterate: Iterate - iterateSettings: IterateSettings - IterateObjectName: string - } -} - -// Switch from unknown to the partner SDK client types -export const destination: BrowserDestinationDefinition = { - name: 'Iterate Web (Actions)', - slug: 'actions-iterate', - mode: 'device', - presets: [ - { - name: 'Track Event', - subscribe: 'type = "track"', - partnerAction: 'trackEvent', - mapping: defaultValues(trackEvent.fields), - type: 'automatic' - }, - { - name: 'Identify User', - subscribe: 'type = "identify"', - partnerAction: 'identifyUser', - mapping: defaultValues(identifyUser.fields), - type: 'automatic' - } - ], - - settings: { - // Add any Segment destination settings required here - apiKey: { - label: 'Embed API Key', - description: 'The Embed API Key for your account. You can find this on your settings pages.', - type: 'string', - required: true - } - }, - - initialize: async ({ settings }, deps) => { - // initialize settings - window.iterateSettings = { - apiKey: settings.apiKey, - installOnLoad: false - } - window.IterateObjectName = 'Iterate' - - // Initialize placeholder Iterate command - const iteratePlaceholder = function (...args) { - iteratePlaceholder.command(args) - } - iteratePlaceholder.loaded = false - iteratePlaceholder.q = [] - iteratePlaceholder.command = function (args: unknown[]) { - iteratePlaceholder.q.push(args) - } - window.Iterate = iteratePlaceholder - - await deps.loadScript('https://platform.iteratehq.com/loader.js') - await deps.resolveWhen(() => !Object.prototype.hasOwnProperty.call(window.Iterate, 'loaded'), 100) - - return window.Iterate - }, - - actions: { - trackEvent, - identifyUser - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/iterate/src/trackEvent/__tests__/index.test.ts b/packages/browser-destinations/destinations/iterate/src/trackEvent/__tests__/index.test.ts deleted file mode 100644 index a1b89f9f38..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/trackEvent/__tests__/index.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import iterateDestination, { destination } from '../../index' - -describe('Iterate.trackEvent', () => { - it('Sends events to Iterate', async () => { - const [trackEvent] = await iterateDestination({ - apiKey: 'abc123', - subscriptions: [ - { - partnerAction: 'trackEvent', - name: 'Track Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - name: { - '@path': '$.name' - } - } - } - ] - }) - - destination.actions.trackEvent.perform = jest.fn() - const trackSpy = jest.spyOn(destination.actions.trackEvent, 'perform') - await trackEvent.load(Context.system(), {} as Analytics) - - await trackEvent.track?.( - new Context({ - type: 'track', - name: 'example-event' - }) - ) - - expect(trackSpy).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - name: 'example-event' - } - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/iterate/src/trackEvent/generated-types.ts b/packages/browser-destinations/destinations/iterate/src/trackEvent/generated-types.ts deleted file mode 100644 index a15b4cba52..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/trackEvent/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The name of the event. - */ - name: string -} diff --git a/packages/browser-destinations/destinations/iterate/src/trackEvent/index.ts b/packages/browser-destinations/destinations/iterate/src/trackEvent/index.ts deleted file mode 100644 index 133369c053..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/trackEvent/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import { Iterate as IterateClient, Command } from '../types' - -const action: BrowserActionDefinition = { - title: 'Track Event', - description: 'Track events', - platform: 'web', - defaultSubscription: 'type = "track"', - fields: { - name: { - description: 'The name of the event.', - label: 'Name', - required: true, - type: 'string', - default: { - '@path': '$.event' - } - } - }, - perform: (Iterate, event) => { - Iterate(Command.Event, event.payload.name) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/iterate/src/types.ts b/packages/browser-destinations/destinations/iterate/src/types.ts deleted file mode 100644 index 0f0893a2c5..0000000000 --- a/packages/browser-destinations/destinations/iterate/src/types.ts +++ /dev/null @@ -1,23 +0,0 @@ -export type Iterate = (command: Command, ...args: unknown[]) => void - -export enum Command { - Event = 'event', - Install = 'install', - Identify = 'identify', - OnResponse = 'onResponse', - OnLoad = 'onLoad', - onClose = 'onClose', - Uninstall = 'uninstall' -} - -export type IterateApi = { - (): void - q: unknown[] - command: (args: unknown[]) => void - loaded: boolean -} - -export type IterateSettings = { - apiKey: string - installOnLoad?: boolean -} diff --git a/packages/browser-destinations/destinations/iterate/tsconfig.json b/packages/browser-destinations/destinations/iterate/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/iterate/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/jimo/README.md b/packages/browser-destinations/destinations/jimo/README.md deleted file mode 100644 index be894a1ed3..0000000000 --- a/packages/browser-destinations/destinations/jimo/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# @segment/analytics-browser-actions-jimo - -The Jimo browser action destination for use with @segment/analytics-next. - -## License - -MIT License - -Copyright (c) 2024 Segment - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -## Contributing - -All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. diff --git a/packages/browser-destinations/destinations/jimo/package.json b/packages/browser-destinations/destinations/jimo/package.json deleted file mode 100644 index 5352c56e66..0000000000 --- a/packages/browser-destinations/destinations/jimo/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-jimo", - "version": "1.35.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/jimo/src/generated-types.ts b/packages/browser-destinations/destinations/jimo/src/generated-types.ts deleted file mode 100644 index 89ab4c93fd..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * Id of the Jimo project. You can find the Project Id here: https://i.usejimo.com/settings/install/portal - */ - projectId: string -} diff --git a/packages/browser-destinations/destinations/jimo/src/index.ts b/packages/browser-destinations/destinations/jimo/src/index.ts deleted file mode 100644 index fd06c0c8d5..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { defaultValues } from '@segment/actions-core' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from './generated-types' -import { initScript } from './init-script' -import sendTrackEvent from './sendTrackEvent' -import sendUserData from './sendUserData' -import { JimoSDK } from './types' - -declare global { - interface Window { - jimo: JimoSDK | never[] - JIMO_PROJECT_ID: string - JIMO_MANUAL_INIT: boolean - } -} - -const ENDPOINT_UNDERCITY = 'https://undercity.usejimo.com/jimo-invader.js' - -export const destination: BrowserDestinationDefinition = { - name: 'Jimo (Actions)', - slug: 'actions-jimo', - mode: 'device', - description: 'Load Jimo SDK and send user profile data to Jimo', - - settings: { - projectId: { - description: - 'Id of the Jimo project. You can find the Project Id here: https://i.usejimo.com/settings/install/portal', - label: 'Id', - type: 'string', - required: true - } - }, - presets: [ - { - name: 'Send User Data', - subscribe: 'type = "identify"', - partnerAction: 'sendUserData', - mapping: defaultValues(sendUserData.fields), - type: 'automatic' - }, - { - name: 'Send Track Event', - subscribe: 'type = "track"', - partnerAction: 'sendTrackEvent', - mapping: defaultValues(sendTrackEvent.fields), - type: 'automatic' - } - ], - initialize: async ({ settings }, deps) => { - initScript(settings) - - await deps.loadScript(`${ENDPOINT_UNDERCITY}`) - - await deps.resolveWhen(() => Array.isArray(window.jimo) === false, 100) - - return window.jimo as JimoSDK - }, - actions: { - sendUserData, - sendTrackEvent - } -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/jimo/src/init-script.ts b/packages/browser-destinations/destinations/jimo/src/init-script.ts deleted file mode 100644 index a93d29eed8..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/init-script.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Settings } from './generated-types' -/* eslint-disable */ -// @ts-nocheck -export function initScript(settings: Settings) { - if (window.jimo) { - return - } - - window.jimo = [] - window['JIMO_PROJECT_ID'] = settings.projectId -} diff --git a/packages/browser-destinations/destinations/jimo/src/sendTrackEvent/__tests__/index.test.ts b/packages/browser-destinations/destinations/jimo/src/sendTrackEvent/__tests__/index.test.ts deleted file mode 100644 index 7af2ff272b..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/sendTrackEvent/__tests__/index.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' -import sendTrackEvent from '..' -import { JimoSDK } from '../../types' -import { Payload } from '../generated-types' - -describe('Jimo - Send Track Event', () => { - test('do:segmentio:track is called', async () => { - const client = { - push: jest.fn() - } as any as JimoSDK - - const context = new Context({ - type: 'track' - }) - - await sendTrackEvent.perform(client as any as JimoSDK, { - settings: { projectId: 'unk' }, - analytics: jest.fn() as any as Analytics, - context: context, - payload: { - messageId: '42', - timestamp: 'timestamp-as-iso-string', - userId: 'u1', - anonymousId: 'a1', - event_name: 'foo', - properties: { - foo: 'bar' - } - } as Payload - }) - - expect(client.push).toHaveBeenCalled() - expect(client.push).toHaveBeenCalledWith([ - 'do', - 'segmentio:track', - [ - { - event: 'foo', - messageId: '42', - timestamp: 'timestamp-as-iso-string', - receivedAt: 'timestamp-as-iso-string', - userId: 'u1', - anonymousId: 'a1', - properties: { - foo: 'bar' - } - } - ] - ]) - }) -}) diff --git a/packages/browser-destinations/destinations/jimo/src/sendTrackEvent/generated-types.ts b/packages/browser-destinations/destinations/jimo/src/sendTrackEvent/generated-types.ts deleted file mode 100644 index b3f2dddd97..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/sendTrackEvent/generated-types.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The internal id of the message. - */ - messageId: string - /** - * The timestamp of the event. - */ - timestamp: string - /** - * The name of the event. - */ - event_name: string - /** - * A unique identifier for the user. - */ - userId?: string - /** - * An anonymous identifier for the user. - */ - anonymousId?: string - /** - * Information associated with the event - */ - properties?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/jimo/src/sendTrackEvent/index.ts b/packages/browser-destinations/destinations/jimo/src/sendTrackEvent/index.ts deleted file mode 100644 index 64cf089125..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/sendTrackEvent/index.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import { JimoSDK } from 'src/types' -import type { Settings } from '../generated-types' -import { Payload } from './generated-types' - -const action: BrowserActionDefinition = { - title: 'Send Track Event', - description: 'Submit an event to Jimo', - defaultSubscription: 'type = "track"', - platform: 'web', - fields: { - messageId: { - description: 'The internal id of the message.', - label: 'Message Id', - type: 'string', - required: true, - default: { - '@path': '$.messageId' - } - }, - timestamp: { - description: 'The timestamp of the event.', - label: 'Timestamp', - type: 'string', - required: true, - default: { - '@path': '$.timestamp' - } - }, - event_name: { - description: 'The name of the event.', - label: 'Event Name', - type: 'string', - required: true, - default: { - '@path': '$.event' - } - }, - userId: { - description: 'A unique identifier for the user.', - label: 'User ID', - type: 'string', - required: false, - default: { - '@path': '$.userId' - } - }, - anonymousId: { - description: 'An anonymous identifier for the user.', - label: 'Anonymous ID', - type: 'string', - required: false, - default: { - '@path': '$.anonymousId' - } - }, - properties: { - description: 'Information associated with the event', - label: 'Event Properties', - type: 'object', - required: false, - default: { - '@path': '$.properties' - } - } - }, - perform: (jimo, { payload }) => { - const { event_name, userId, anonymousId, timestamp, messageId, properties } = payload - const receivedAt = timestamp - - jimo.push([ - 'do', - 'segmentio:track', - [{ event: event_name, userId, anonymousId, messageId, timestamp, receivedAt, properties }] - ]) - window.dispatchEvent(new CustomEvent(`jimo-segmentio-track:${event_name}`)) - } -} - -export default action diff --git a/packages/browser-destinations/destinations/jimo/src/sendUserData/__tests__/index.test.ts b/packages/browser-destinations/destinations/jimo/src/sendUserData/__tests__/index.test.ts deleted file mode 100644 index 0e5d5c95ff..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/sendUserData/__tests__/index.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Analytics, Context } from '@segment/analytics-next' - -import sendUserData from '..' -import { JimoSDK } from '../../types' -import { Payload } from '../generated-types' - -describe('Jimo - Send User Data', () => { - test('user id', async () => { - const client = { - push: jest.fn() - } as any as JimoSDK - - const context = new Context({ - type: 'identify' - }) - - await sendUserData.perform(client as any as JimoSDK, { - settings: { projectId: 'unk' }, - analytics: jest.fn() as any as Analytics, - context: context, - payload: { - userId: 'u1' - } as Payload - }) - - expect(client.push).toHaveBeenCalled() - expect(client.push).toHaveBeenCalledWith(['set', 'user:id', ['u1']]) - }) - test('user email', async () => { - const client = { - push: jest.fn() - } as any as JimoSDK - - const context = new Context({ - type: 'identify' - }) - - await sendUserData.perform(client as any as JimoSDK, { - settings: { projectId: 'unk' }, - analytics: jest.fn() as any as Analytics, - context: context, - payload: { - email: 'foo@bar.com' - } as Payload - }) - - expect(client.push).toHaveBeenCalled() - expect(client.push).toHaveBeenCalledWith(['set', 'user:email', ['foo@bar.com']]) - }) - test('user traits', async () => { - const client = { - push: jest.fn() - } as any as JimoSDK - - const context = new Context({ - type: 'identify' - }) - - await sendUserData.perform(client as any as JimoSDK, { - settings: { projectId: 'unk' }, - analytics: jest.fn() as any as Analytics, - context: context, - payload: { - traits: { - trait1: true, - trait2: 'foo', - trait3: 1 - } - } as Payload - }) - - expect(client.push).toHaveBeenCalled() - expect(client.push).toHaveBeenCalledWith([ - 'set', - 'user:attributes', - [ - { - trait1: true, - trait2: 'foo', - trait3: 1 - }, - false, - true - ] - ]) - }) -}) diff --git a/packages/browser-destinations/destinations/jimo/src/sendUserData/generated-types.ts b/packages/browser-destinations/destinations/jimo/src/sendUserData/generated-types.ts deleted file mode 100644 index 3105bc1871..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/sendUserData/generated-types.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The unique user identifier - */ - userId?: string | null - /** - * The email of the user - */ - email?: string | null - /** - * A list of attributes coming from segment traits - */ - traits?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/jimo/src/sendUserData/index.ts b/packages/browser-destinations/destinations/jimo/src/sendUserData/index.ts deleted file mode 100644 index a6ee2c1a75..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/sendUserData/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import { JimoSDK } from 'src/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' - -const action: BrowserActionDefinition = { - title: 'Send User Data', - description: 'Send user ID and email to Jimo', - platform: 'web', - fields: { - userId: { - label: 'User ID', - description: 'The unique user identifier', - type: 'string', - allowNull: true, - required: false, - default: { - '@path': '$.userId' - } - }, - email: { - label: 'User email', - description: 'The email of the user', - type: 'string', - allowNull: true, - required: false, - default: { - '@path': '$.traits.email' - } - }, - traits: { - label: 'User Traits', - description: 'A list of attributes coming from segment traits', - type: 'object', - default: { - '@path': '$.traits' - } - } - }, - defaultSubscription: 'type = "identify"', - perform: (jimo, { payload }) => { - if (payload.userId != null) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - jimo.push(['set', 'user:id', [payload.userId]]) - } - if (payload.email != null) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - jimo.push(['set', 'user:email', [payload.email]]) - } - if (payload.traits != null) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - jimo.push(['set', 'user:attributes', [payload.traits, false, true]]) - } - } -} - -export default action diff --git a/packages/browser-destinations/destinations/jimo/src/types.ts b/packages/browser-destinations/destinations/jimo/src/types.ts deleted file mode 100644 index 0bb96075b5..0000000000 --- a/packages/browser-destinations/destinations/jimo/src/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface JimoSDK { - push: (params: Array) => Promise -} diff --git a/packages/browser-destinations/destinations/jimo/tsconfig.json b/packages/browser-destinations/destinations/jimo/tsconfig.json deleted file mode 100644 index c2a7897afd..0000000000 --- a/packages/browser-destinations/destinations/jimo/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} diff --git a/packages/browser-destinations/destinations/koala/package.json b/packages/browser-destinations/destinations/koala/package.json deleted file mode 100644 index ad5f752b12..0000000000 --- a/packages/browser-destinations/destinations/koala/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-koala", - "version": "1.48.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/actions-core": "^3.116.0", - "@segment/browser-destination-runtime": "^1.46.0" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/koala/src/generated-types.ts b/packages/browser-destinations/destinations/koala/src/generated-types.ts deleted file mode 100644 index 8bfe329ec2..0000000000 --- a/packages/browser-destinations/destinations/koala/src/generated-types.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * Please enter your Public API Key found in your Koala workspace settings. - */ - project_slug: string -} diff --git a/packages/browser-destinations/destinations/koala/src/identifyVisitor/__tests__/index.test.ts b/packages/browser-destinations/destinations/koala/src/identifyVisitor/__tests__/index.test.ts deleted file mode 100644 index 213b90176b..0000000000 --- a/packages/browser-destinations/destinations/koala/src/identifyVisitor/__tests__/index.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -import type { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import KoalaDestination, { destination } from '../../index' - -import { loadScript } from '@segment/browser-destination-runtime/load-script' -jest.mock('@segment/browser-destination-runtime/load-script') -beforeEach(async () => { - ;(loadScript as jest.Mock).mockResolvedValue(true) -}) - -const subscriptions: Subscription[] = [ - { - partnerAction: 'identifyVisitor', - name: 'Identify Visitor', - enabled: true, - subscribe: 'type = "identify"', - mapping: { - traits: { - '@path': '$.traits' - } - } - } -] - -describe('Koala.identifyVisitor', () => { - test('it maps traits and passes them into ko.identify', async () => { - window.ko = { - ready: jest.fn(), - track: jest.fn().mockResolvedValueOnce(undefined), - identify: jest.fn().mockResolvedValueOnce(undefined) - } - window.KoalaSDK = { - load: jest.fn().mockResolvedValueOnce(window.ko) - } - - const [event] = await KoalaDestination({ - subscriptions, - project_slug: 'koala-test' - }) - - const ajs = new Analytics({ writeKey: 'w_123' }) - await event.load(Context.system(), ajs) - jest.spyOn(destination.actions.identifyVisitor, 'perform') - - await event.identify?.( - new Context({ - type: 'identify', - traits: { - name: 'Matt' - } - }) - ) - - expect(destination.actions.identifyVisitor.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - traits: { - name: 'Matt' - } - } - }) - ) - expect(window.ko.identify).toHaveBeenCalledWith( - expect.objectContaining({ - name: 'Matt' - }), - expect.objectContaining({ - source: 'segment-browser' - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/koala/src/identifyVisitor/generated-types.ts b/packages/browser-destinations/destinations/koala/src/identifyVisitor/generated-types.ts deleted file mode 100644 index 84b9dda38d..0000000000 --- a/packages/browser-destinations/destinations/koala/src/identifyVisitor/generated-types.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * Traits to associate with the visitor in Koala. - */ - traits: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/koala/src/identifyVisitor/index.ts b/packages/browser-destinations/destinations/koala/src/identifyVisitor/index.ts deleted file mode 100644 index e334b82075..0000000000 --- a/packages/browser-destinations/destinations/koala/src/identifyVisitor/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { Koala } from '../types' - -const action: BrowserActionDefinition = { - title: 'Identify Visitor', - description: 'Update visitor traits in Koala.', - defaultSubscription: 'type = "identify"', - platform: 'web', - fields: { - traits: { - type: 'object', - label: 'Traits', - description: 'Traits to associate with the visitor in Koala.', - required: true, - default: { '@path': '$.traits' }, - defaultObjectUI: 'object' - } - }, - perform: (koala, { payload }) => { - if (payload?.traits) { - return koala.identify(payload.traits, { source: 'segment-browser' }) - } - } -} - -export default action diff --git a/packages/browser-destinations/destinations/koala/src/index.ts b/packages/browser-destinations/destinations/koala/src/index.ts deleted file mode 100644 index c991ac6db1..0000000000 --- a/packages/browser-destinations/destinations/koala/src/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { Settings } from './generated-types' -import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types' -import type { KoalaSDK, Koala } from './types' -import { defaultValues } from '@segment/actions-core' -import { browserDestination } from '@segment/browser-destination-runtime/shim' -import { initScript } from './init-script' -import trackEvent from './trackEvent' -import identifyVisitor from './identifyVisitor' - -declare global { - interface Window { - ko: Koala - KoalaSDK: KoalaSDK - } -} - -export const destination: BrowserDestinationDefinition = { - name: 'Koala', - slug: 'actions-koala', - description: 'Connect Koala in Segment to send visitor events or traits to Koala.', - mode: 'device', - settings: { - project_slug: { - type: 'string', - label: 'Public API Key', - description: 'Please enter your Public API Key found in your Koala workspace settings.', - required: true - } - }, - - initialize: async ({ settings, analytics }, deps) => { - initScript() - await deps.loadScript(`https://cdn.getkoala.com/v1/${settings.project_slug}/umd.js`) - - const ko = await window.KoalaSDK.load({ - project: settings.project_slug, - hookSegment: false - }) - - void analytics.ready(() => ko.ready(() => ko.identify(analytics.user().traits() as Record))) - - return ko - }, - - actions: { - trackEvent, - identifyVisitor - }, - - presets: [ - { - name: 'Track Event', - subscribe: 'type = "track"', - partnerAction: 'trackEvent', - mapping: defaultValues(trackEvent.fields), - type: 'automatic' - }, - { - name: 'Identify Visitor', - subscribe: 'type = "identify"', - partnerAction: 'identifyVisitor', - mapping: defaultValues(identifyVisitor.fields), - type: 'automatic' - } - ] -} - -export default browserDestination(destination) diff --git a/packages/browser-destinations/destinations/koala/src/init-script.ts b/packages/browser-destinations/destinations/koala/src/init-script.ts deleted file mode 100644 index 7a50db0040..0000000000 --- a/packages/browser-destinations/destinations/koala/src/init-script.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -export function initScript() { - if (window.ko) { - return - } - - window.ko = [] - ;['identify', 'track', 'removeListeners', 'open', 'on', 'off', 'qualify', 'ready'].forEach(function (method) { - ko[method] = function () { - let args = Array.from(arguments) - args.unshift(method) - ko.push(args) - return ko - } - }) -} diff --git a/packages/browser-destinations/destinations/koala/src/trackEvent/__tests__/index.test.ts b/packages/browser-destinations/destinations/koala/src/trackEvent/__tests__/index.test.ts deleted file mode 100644 index dfc33cd984..0000000000 --- a/packages/browser-destinations/destinations/koala/src/trackEvent/__tests__/index.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type { Subscription } from '@segment/browser-destination-runtime/types' -import { Analytics, Context } from '@segment/analytics-next' -import KoalaDestination, { destination } from '../../index' - -import { loadScript } from '@segment/browser-destination-runtime/load-script' -jest.mock('@segment/browser-destination-runtime/load-script') -beforeEach(async () => { - ;(loadScript as jest.Mock).mockResolvedValue(true) -}) - -const subscriptions: Subscription[] = [ - { - partnerAction: 'trackEvent', - name: 'Track Event', - enabled: true, - subscribe: 'type = "track"', - mapping: { - event: { - '@path': '$.event' - }, - properties: { - '@path': '$.properties' - } - } - } -] - -describe('Koala.trackEvent', () => { - test('it maps the event name and properties and passes them into ko.track', async () => { - window.ko = { - ready: jest.fn(), - track: jest.fn().mockResolvedValueOnce(undefined), - identify: jest.fn().mockResolvedValueOnce(undefined) - } - window.KoalaSDK = { - load: jest.fn().mockResolvedValueOnce(window.ko) - } - - const [event] = await KoalaDestination({ - subscriptions, - project_slug: 'koala-test' - }) - - const ajs = new Analytics({ writeKey: 'w_123' }) - await event.load(Context.system(), ajs) - jest.spyOn(destination.actions.trackEvent, 'perform') - - await event.track?.( - new Context({ - type: 'track', - event: 'Form Submitted', - properties: { - is_new_subscriber: true - } - }) - ) - - expect(destination.actions.trackEvent.perform).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - payload: { - event: 'Form Submitted', - properties: { - is_new_subscriber: true - } - } - }) - ) - expect(window.ko.track).toHaveBeenCalledWith( - 'Form Submitted', - expect.objectContaining({ - is_new_subscriber: true - }) - ) - }) -}) diff --git a/packages/browser-destinations/destinations/koala/src/trackEvent/generated-types.ts b/packages/browser-destinations/destinations/koala/src/trackEvent/generated-types.ts deleted file mode 100644 index e9d44322e2..0000000000 --- a/packages/browser-destinations/destinations/koala/src/trackEvent/generated-types.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Payload { - /** - * The event name. - */ - event: string - /** - * Properties to send with the event. - */ - properties?: { - [k: string]: unknown - } -} diff --git a/packages/browser-destinations/destinations/koala/src/trackEvent/index.ts b/packages/browser-destinations/destinations/koala/src/trackEvent/index.ts deleted file mode 100644 index 81c990fef9..0000000000 --- a/packages/browser-destinations/destinations/koala/src/trackEvent/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types' -import type { Settings } from '../generated-types' -import type { Payload } from './generated-types' -import type { Koala } from '../types' - -const action: BrowserActionDefinition = { - title: 'Track Event', - description: 'Send visitor events to Koala.', - defaultSubscription: 'type = "track"', - platform: 'web', - fields: { - event: { - type: 'string', - required: true, - description: 'The event name.', - label: 'Event Name', - default: { '@path': '$.event' } - }, - properties: { - type: 'object', - required: false, - description: 'Properties to send with the event.', - label: 'Event Properties', - default: { '@path': '$.properties' }, - defaultObjectUI: 'object' - } - }, - perform: (koala, { payload }) => { - if (payload?.event) { - return koala.track(payload.event, payload.properties) - } - } -} - -export default action diff --git a/packages/browser-destinations/destinations/koala/src/types.ts b/packages/browser-destinations/destinations/koala/src/types.ts deleted file mode 100644 index f13839c938..0000000000 --- a/packages/browser-destinations/destinations/koala/src/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface Koala { - ready: (fn?: () => Promise | unknown) => Promise - track: (event: string, data?: { [key: string]: unknown }) => Promise - identify: (traits: Record, options?: { source?: string }) => Promise -} - -export interface KoalaSDK { - load: (options: { project: string; hookSegment?: boolean }) => Promise -} diff --git a/packages/browser-destinations/destinations/koala/tsconfig.json b/packages/browser-destinations/destinations/koala/tsconfig.json deleted file mode 100644 index 71c49219d9..0000000000 --- a/packages/browser-destinations/destinations/koala/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "baseUrl": "." - }, - "include": ["src"], - "exclude": ["dist", "**/__tests__"] -} \ No newline at end of file diff --git a/packages/browser-destinations/destinations/logrocket/package.json b/packages/browser-destinations/destinations/logrocket/package.json deleted file mode 100644 index 32fbcecee3..0000000000 --- a/packages/browser-destinations/destinations/logrocket/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@segment/analytics-browser-actions-logrocket", - "version": "1.47.0", - "license": "MIT", - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org" - }, - "main": "./dist/cjs", - "module": "./dist/esm", - "scripts": { - "build": "yarn build:esm && yarn build:cjs", - "build:cjs": "tsc --module commonjs --outDir ./dist/cjs", - "build:esm": "tsc --outDir ./dist/esm" - }, - "typings": "./dist/esm", - "dependencies": { - "@segment/actions-core": "^3.116.0", - "@segment/browser-destination-runtime": "^1.46.0", - "logrocket": "^3.0.1" - }, - "peerDependencies": { - "@segment/analytics-next": ">=1.55.0" - } -} diff --git a/packages/browser-destinations/destinations/logrocket/src/__tests__/index.test.ts b/packages/browser-destinations/destinations/logrocket/src/__tests__/index.test.ts deleted file mode 100644 index 47a1f74518..0000000000 --- a/packages/browser-destinations/destinations/logrocket/src/__tests__/index.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* -import { Analytics, Context } from '@segment/analytics-next' -import plugins, { destination } from '../index' -import { mockWorkerAndXMLHttpRequest, subscriptions } from '../test_utilities' -import Logrocket from 'logrocket' -*/ -//jest.mock('logrocket') - -//const appID = 'log/rocket' - -describe('Logrocket', () => { - //beforeAll(mockWorkerAndXMLHttpRequest) - //afterAll(jest.restoreAllMocks) - - test('can load', async () => { - /* - const [event] = await plugins({ - appID, - networkSanitization: false, - inputSanitization: false, - subscriptions - }) - - jest.spyOn(destination, 'initialize') - jest.spyOn(Logrocket, 'init') - - await event.load(Context.system(), {} as Analytics) - expect(destination.initialize).toHaveBeenCalled() - expect(Logrocket.init).toHaveBeenCalled() - - expect(window._LRLogger).toBeDefined() - */ - expect(true) - }) - - /* - test('supplies the input sanitization parameter', async () => { - const [event] = await plugins({ - appID, - networkSanitization: false, - inputSanitization: true, - subscriptions - }) - - jest.spyOn(Logrocket, 'init') - - await event.load(Context.system(), {} as Analytics) - expect(Logrocket.init).toHaveBeenCalledWith(appID, expect.objectContaining({ dom: { inputSanitizer: true } })) - }) - - describe('network sanitizer', () => { - test('redacts requests when configured', async () => { - const [event] = await plugins({ - appID, - networkSanitization: true, - inputSanitization: false, - subscriptions - }) - - const spy = jest.spyOn(Logrocket, 'init') - - await event.load(Context.system(), {} as Analytics) - expect(Logrocket.init).toHaveBeenCalledWith(appID, expect.objectContaining({ dom: { inputSanitizer: false } })) - const requestSanitizer: RequestSanitizer = spy.mock.calls[0][1]?.network?.requestSanitizer - - if (!requestSanitizer) fail('request sanitizer null') - - const mockRequest = { - body: 'hello', - headers: { goodbye: 'moon' }, - reqId: 'something', - url: 'neat', - method: 'get' - } - - const sanitizedResult = requestSanitizer(mockRequest) - - expect(sanitizedResult).toEqual(expect.objectContaining({ body: undefined, headers: {} })) - }) - - test('does not modify requests if disabled', async () => { - const [event] = await plugins({ - appID, - networkSanitization: false, - inputSanitization: false, - subscriptions - }) - - const spy = jest.spyOn(Logrocket, 'init') - - await event.load(Context.system(), {} as Analytics) - expect(Logrocket.init).toHaveBeenCalledWith(appID, expect.objectContaining({ dom: { inputSanitizer: false } })) - const requestSanitizer: RequestSanitizer = spy.mock.calls[0][1]?.network?.requestSanitizer - - if (!requestSanitizer) fail('request sanitizer null') - - const mockRequest = { - body: 'hello', - headers: { goodbye: 'moon' }, - reqId: 'something', - url: 'neat', - method: 'get' - } - - const sanitizedResult = requestSanitizer(mockRequest) - - expect(sanitizedResult).toEqual(mockRequest) - }) - }) - - */ -}) diff --git a/packages/browser-destinations/destinations/logrocket/src/generated-types.ts b/packages/browser-destinations/destinations/logrocket/src/generated-types.ts deleted file mode 100644 index b1f23f24f9..0000000000 --- a/packages/browser-destinations/destinations/logrocket/src/generated-types.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Generated file. DO NOT MODIFY IT BY HAND. - -export interface Settings { - /** - * The LogRocket app ID. - */ - appID: string - /** - * Sanitize all network request and response bodies from session recordings. - */ - networkSanitization: boolean - /** - * Obfuscate all user-input elements (like and and - -
-

Settings

- -
- - -
-

Event

- -
- - - -
-
- -

-  

-
-  
-
-  
-
-
-
\ No newline at end of file
diff --git a/packages/browser-destinations/package.json b/packages/browser-destinations/package.json
deleted file mode 100644
index baee9a8f2a..0000000000
--- a/packages/browser-destinations/package.json
+++ /dev/null
@@ -1,90 +0,0 @@
-{
-  "name": "@segment/browser-destinations",
-  "private": true,
-  "version": "0.0.0",
-  "description": "Action based browser destinations",
-  "author": "Netto Farah",
-  "license": "MIT",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/segmentio/action-destinations",
-    "directory": "packages/browser-destinations"
-  },
-  "scripts": {
-    "analyze": "NODE_ENV=production webpack --profile --json > stats.json && webpack-bundle-analyzer --port 4200 stats.json",
-    "build-web": "yarn clean && bash scripts/build-web.sh",
-    "build-web-stage": "bash scripts/build-web-stage.sh",
-    "deploy-prod": "yarn build-web && aws s3 sync ./dist/web/ s3://segment-ajs-next-destinations-production/next-integrations/actions --grants read=id=$npm_config_prod_cdn_oai,id=$npm_config_prod_custom_domain_oai",
-    "deploy-stage": "yarn build-web-stage && aws-okta exec plat-write -- aws s3 sync ./dist/web/ s3://segment-ajs-next-destinations-stage/next-integrations/actions --grants read=id=$npm_config_stage_cdn_oai,id=$npm_config_stage_custom_domain_oai",
-    "clean": "rm -rf dist",
-    "prepublishOnly": "yarn build",
-    "test": "jest",
-    "typecheck": "tsc -p tsconfig.build.json --noEmit",
-    "dev": "NODE_ENV=development NODE_OPTIONS=--openssl-legacy-provider concurrently \"webpack serve\" \"webpack -c webpack.config.js --watch\"",
-    "size": "size-limit"
-  },
-  "dependencies": {
-    "tslib": "^2.3.1",
-    "vm-browserify": "^1.1.2"
-  },
-  "devDependencies": {
-    "@babel/core": "^7.13.16",
-    "@babel/plugin-proposal-class-properties": "^7.13.0",
-    "@babel/plugin-transform-modules-commonjs": "^7.13.8",
-    "@babel/preset-env": "^7.13.10",
-    "@babel/preset-typescript": "^7.13.0",
-    "@size-limit/preset-big-lib": "^11.0.1",
-    "@types/gtag.js": "^0.0.19",
-    "@types/jest": "^27.0.0",
-    "compression-webpack-plugin": "^7.1.2",
-    "concurrently": "^6.3.0",
-    "globby": "^11.0.2",
-    "jest": "^27.3.1",
-    "serve": "^12.0.1",
-    "size-limit": "^11.0.1",
-    "terser-webpack-plugin": "^5.1.1",
-    "ts-loader": "^9.2.6",
-    "webpack": "^5.82.0",
-    "webpack-bundle-analyzer": "^4.4.1",
-    "webpack-cli": "^5.1.1",
-    "webpack-dev-server": "^4.15.0",
-    "webpack-manifest-plugin": "^5.0.0"
-  },
-  "jest": {
-    "testEnvironment": "jsdom",
-    "testEnvironmentOptions": {
-      "runScripts": "dangerously",
-      "resources": "usable",
-      "url": "https://segment.com"
-    },
-    "rootDir": "./",
-    "moduleNameMapper": {
-      "@segment/ajv-human-errors": "/../ajv-human-errors/src",
-      "@segment/actions-core": "/../core/src",
-      "@segment/destination-subscriptions": "/../destination-subscriptions/src",
-      "@segment/actions-shared": "/../actions-shared/src",
-      "@segment/browser-destination-runtime/(.*)": "/../browser-destination-runtime/src/$1"
-    },
-    "globals": {
-      "ts-jest": {
-        "isolatedModules": true
-      }
-    },
-    "transform": {
-      "^.+\\.[t|j]sx?$": "ts-jest"
-    },
-    "transformIgnorePatterns": [
-      "/node_modules/(?!(@segment/analytics-next|@braze/web-sdk/)).+\\.js$"
-    ],
-    "setupFilesAfterEnv": [
-      "/test/setup-after-env.ts"
-    ],
-    "forceExit": true
-  },
-  "size-limit": [
-    {
-      "path": "dist/web/*/*.js",
-      "limit": "159 KB"
-    }
-  ]
-}
diff --git a/packages/browser-destinations/scripts/build-es.sh b/packages/browser-destinations/scripts/build-es.sh
deleted file mode 100755
index f63bc48b36..0000000000
--- a/packages/browser-destinations/scripts/build-es.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-find ./destinations -maxdepth 1 -mindepth 1 -type d -exec bash -c "cd '{}' && pwd && yarn tsc --build" \;
\ No newline at end of file
diff --git a/packages/browser-destinations/scripts/build-web-stage.sh b/packages/browser-destinations/scripts/build-web-stage.sh
deleted file mode 100755
index 73f5a4dc75..0000000000
--- a/packages/browser-destinations/scripts/build-web-stage.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-NODE_VERSION="$(node --version)";
-NODE_VERSION_MAJOR="${NODE_VERSION:1}"; # strip the "v"  prefix
-NODE_VERSION_MAJOR="${NODE_VERSION_MAJOR%%.*}"; #get everything before the first dot
-if [ "$NODE_VERSION_MAJOR" -ge "18" ]; then
-NODE_ENV=production ASSET_ENV=stage NODE_OPTIONS=--openssl-legacy-provider yarn webpack -c webpack.config.js
-else NODE_ENV=production ASSET_ENV=stage yarn webpack -c webpack.config.js
-fi
-
-
-
diff --git a/packages/browser-destinations/scripts/build-web.sh b/packages/browser-destinations/scripts/build-web.sh
deleted file mode 100755
index fcd1016d78..0000000000
--- a/packages/browser-destinations/scripts/build-web.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-NODE_VERSION="$(node --version)";
-NODE_VERSION_MAJOR="${NODE_VERSION:1}"; # strip the "v"  prefix
-NODE_VERSION_MAJOR="${NODE_VERSION_MAJOR%%.*}"; #get everything before the first dot
-if [ "$NODE_VERSION_MAJOR" -ge "18" ]; then
-NODE_ENV=production ASSET_ENV=production NODE_OPTIONS=--openssl-legacy-provider yarn webpack -c webpack.config.js
-else NODE_ENV=production ASSET_ENV=production yarn webpack -c webpack.config.js
-fi
diff --git a/packages/browser-destinations/test/setup-after-env.ts b/packages/browser-destinations/test/setup-after-env.ts
deleted file mode 100644
index f7e09beabd..0000000000
--- a/packages/browser-destinations/test/setup-after-env.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { Crypto } from '@peculiar/webcrypto'
-import { TextEncoder, TextDecoder } from 'util'
-import { setImmediate } from 'timers'
-
-// fix: "ReferenceError: TextEncoder is not defined" after upgrading JSDOM
-global.TextEncoder = TextEncoder
-global.TextDecoder = TextDecoder
-// fix: jsdom uses setImmediate under the hood for preflight XHR requests,
-// and jest removed setImmediate, so we need to provide it to prevent console
-// logging ReferenceErrors made by integration tests that call Amplitude.
-global.setImmediate = setImmediate
-
-beforeEach(() => {
-  jest.restoreAllMocks()
-  jest.resetAllMocks()
-
-  // Reset the body and head between tests
-  document.body.innerHTML = ''
-  document.head.innerHTML = ''
-
-  // Add a script tag to the document so `load-script` works (it expects existing scripts)
-  const script = document.createElement('script')
-  script.innerHTML = `// the emptiness`
-  document.head.appendChild(script)
-
-  jest.spyOn(window, 'window', 'get')
-  jest.spyOn(global, 'document', 'get')
-  jest.spyOn(console, 'error').mockImplementation(() => {})
-  global.document.domain = 'segment.com'
-
-  global.crypto = new Crypto()
-})
diff --git a/packages/browser-destinations/tsconfig.build.json b/packages/browser-destinations/tsconfig.build.json
deleted file mode 100644
index 907c54e8a2..0000000000
--- a/packages/browser-destinations/tsconfig.build.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
-  "extends": "../../tsconfig.json",
-  "compilerOptions": {
-    "module": "esnext",
-    "composite": true,
-    "outDir": "dist",
-    "rootDir": "src",
-    "allowJs": true,
-    "importHelpers": true,
-    "lib": ["es2020", "dom"],
-    "baseUrl": ".",
-    "paths": {
-      "@segment/actions-core": ["../core/src"],
-      "@segment/actions-core/*": ["../core/src/*"],
-      "@segment/actions-shared": ["../actions-shared/src"],
-      "@segment/action-destinations": ["../destination-actions/src"],
-      "@segment/destination-subscriptions": ["../destination-subscriptions/src"],
-      "@segment/browser-destination-runtime": ["../browser-destination-runtime/src"],
-      "@segment/browser-destination-runtime/*": ["../browser-destination-runtime/src/*"]
-    }
-  },
-  "exclude": ["**/__tests__/**/*.ts"],
-  "include": ["src"],
-  "references": [
-    { "path": "../core/tsconfig.build.json" },
-    { "path": "../destination-subscriptions/tsconfig.build.json" },
-    { "path": "../browser-destination-runtime/tsconfig.build.json" }
-  ]
-}
diff --git a/packages/browser-destinations/tsconfig.json b/packages/browser-destinations/tsconfig.json
deleted file mode 100644
index 2d4ba95c55..0000000000
--- a/packages/browser-destinations/tsconfig.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "extends": "../../tsconfig.json",
-  "compilerOptions": {
-    "allowJs": true, // remove ts-jest warning
-    "module": "esnext",
-    "removeComments": false,
-    "baseUrl": ".",
-    "paths": {
-      "@segment/actions-core": ["../core/src"],
-      "@segment/actions-core/*": ["../core/src/*"],
-      "@segment/actions-shared": ["../actions-shared/src"],
-      "@segment/action-destinations": ["../destination-actions/src"],
-      "@segment/destination-subscriptions": ["../destination-subscriptions/src"]
-    }
-  },
-  "exclude": ["webpack.config.js", "dist"]
-}
diff --git a/packages/browser-destinations/webpack.config.js b/packages/browser-destinations/webpack.config.js
deleted file mode 100644
index 7c70996b82..0000000000
--- a/packages/browser-destinations/webpack.config.js
+++ /dev/null
@@ -1,157 +0,0 @@
-const path = require('path')
-const globby = require('globby')
-const TerserPlugin = require('terser-webpack-plugin')
-const CompressionPlugin = require('compression-webpack-plugin')
-const { WebpackManifestPlugin } = require('webpack-manifest-plugin')
-const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
-const webpack = require('webpack')
-
-const files = globby.sync('./destinations/*/src/index.ts')
-const isProd = process.env.NODE_ENV === 'production'
-
-const entries = files.reduce((acc, current) => {
-  const [_dot, _destinations, destination, ..._rest] = current.split('/')
-  return {
-    ...acc,
-    [destination]: current
-  }
-}, {})
-
-const filemap = (file) => {
-  file.path = file.path.split('/').pop() // get the content hash (filename)
-  return file
-}
-
-const sha = require('child_process').execSync('git rev-parse --short HEAD').toString().trim()
-
-const plugins = [
-  new webpack.DefinePlugin({ 'process.env.ASSET_ENV': JSON.stringify(process.env.ASSET_ENV) }),
-  new WebpackManifestPlugin({
-    fileName: `manifest-${sha}.json`,
-    useEntryKeys: true,
-    filter: ({name}) => Object.keys(entries).includes(name),
-    map: filemap
-  }),
-  new WebpackManifestPlugin({
-    fileName: `manifest-latest.json`,
-    useEntryKeys: true,
-    filter: ({name}) => Object.keys(entries).includes(name),
-    map: filemap
-  }),
-]
-
-if (isProd) {
-  plugins.push(new CompressionPlugin())
-}
-
-if (process.env.ANALYZE) {
-  plugins.push(
-    new BundleAnalyzerPlugin({
-      defaultSizes: 'stat'
-    })
-  )
-}
-
-plugins.push(
-  new webpack.optimize.LimitChunkCountPlugin({
-    maxChunks: 1
-  })
-)
-
-const unobfuscatedOutput = {
-  entry: entries,
-  mode: process.env.NODE_ENV || 'development',
-  devtool: 'source-map',
-  output: {
-    chunkFilename: '[name]/[contenthash].js',
-    filename: (file) =>
-      process.env.NODE_ENV === 'development' ? `${file.chunk.name}.js` : `${file.chunk.name}/[contenthash].js`,
-    path: path.resolve(__dirname, 'dist/web'),
-    publicPath: 'auto', // Needed for customers using custom CDNs with analytics.js
-    library: '[name]Destination',
-    libraryTarget: 'window',
-    libraryExport: 'default'
-  },
-  module: {
-    rules: [
-      {
-        test: /\.m?js$/,
-        resolve: {
-          fullySpecified: false,
-        },
-      },
-      {
-        test: /\.ts$/,
-        use: [
-          {
-            loader: 'ts-loader',
-            options: {
-              configFile: 'tsconfig.build.json',
-              projectReferences: true,
-              transpileOnly: true
-            }
-          }
-        ]
-      }
-    ]
-  },
-  resolve: {
-    modules: [
-      // use current node_modules directory first (e.g. for tslib)
-      path.resolve(__dirname, 'node_modules'),
-      'node_modules'
-    ],
-    mainFields: ['exports', 'module', 'browser', 'main'],
-    extensions: ['.ts', '.js'],
-    fallback: {
-      vm: require.resolve('vm-browserify')
-    }
-  },
-  devServer: {
-    liveReload: true,
-    port: 9000,
-    static: {
-      directory: path.resolve(__dirname)
-    }
-  },
-  performance: {
-    hints: 'warning'
-  },
-  optimization: {
-    moduleIds: 'deterministic',
-    minimize: isProd,
-    minimizer: [
-      new TerserPlugin({
-        extractComments: false,
-        terserOptions: {
-          ecma: '2015',
-          mangle: true,
-          compress: true,
-          output: {
-            comments: false
-          }
-        }
-      })
-    ]
-  },
-  plugins
-}
-
-const obfuscatedOutput = {
-  ...unobfuscatedOutput,
-  devServer: {
-    ...unobfuscatedOutput.devServer,
-    port: 9001
-  },
-  output: {
-    ...unobfuscatedOutput.output,
-    filename: (file) => {
-      const obfuscatedOutputName = Buffer.from(file.chunk.name).toString('base64').replace(/=/g, '')
-      return process.env.NODE_ENV === 'development'
-        ? `${obfuscatedOutputName}.js`
-        : `${obfuscatedOutputName}/[contenthash].js`
-    }
-  }
-}
-
-module.exports = [unobfuscatedOutput, obfuscatedOutput]