From 6636770be8d1406f6d8d5f6621f81d97056a3852 Mon Sep 17 00:00:00 2001 From: George Bardis <109069547+bardisg@users.noreply.github.com> Date: Fri, 29 Sep 2023 09:53:38 +0300 Subject: [PATCH] feat(Amplitude): update amplitude SDK (#1413) * feat(Amplitude): update amplitude SDK (#1228) * feat(Amplitude): update amplitude SDK * feat: update logEvent to track * update mobile and web sdk common fields * update default value of trackNewCampaigns * update default eventUploadPeriodMillis to 1000 --------- Co-authored-by: George Bardis <109069547+bardisg@users.noreply.github.com> * feat(analytics-js-integrations): add test of IE11 --------- Co-authored-by: Sudip Paul <67197965+ItsSudip@users.noreply.github.com> Co-authored-by: ItsSudip --- .../src/integrations/Amplitude/browser.js | 82 +++---- .../integrations/Amplitude/nativeSdkLoader.js | 206 +++++++++--------- 2 files changed, 140 insertions(+), 148 deletions(-) diff --git a/packages/analytics-js-integrations/src/integrations/Amplitude/browser.js b/packages/analytics-js-integrations/src/integrations/Amplitude/browser.js index 21d01504f..ae2bcdd4a 100644 --- a/packages/analytics-js-integrations/src/integrations/Amplitude/browser.js +++ b/packages/analytics-js-integrations/src/integrations/Amplitude/browser.js @@ -2,7 +2,6 @@ /* eslint-disable class-methods-use-this */ import { NAME } from '@rudderstack/analytics-js-common/constants/integrations/Amplitude/constants'; import Logger from '../../utils/logger'; -import { type } from '../../utils/utils'; import { loadNativeSdk } from './nativeSdkLoader'; import { getTraitsToSetOnce, getTraitsToIncrement, getDestinationOptions } from './utils'; @@ -19,15 +18,10 @@ class Amplitude { this.trackAllPages = config.trackAllPages || false; this.trackNamedPages = config.trackNamedPages || false; this.trackCategorizedPages = config.trackCategorizedPages || false; - this.trackUtmProperties = config.trackUtmProperties || false; - this.trackReferrer = config.trackReferrer || false; - this.batchEvents = config.batchEvents || false; - this.eventUploadThreshold = +config.eventUploadThreshold || 30; - this.eventUploadPeriodMillis = +config.eventUploadPeriodMillis || 30000; - this.forceHttps = config.forceHttps || false; - this.trackGclid = config.trackGclid || false; - this.saveParamsReferrerOncePerSession = config.saveParamsReferrerOncePerSession || false; - this.deviceIdFromUrlParam = config.deviceIdFromUrlParam || false; + this.attribution = config.attribution || false; + this.flushQueueSize = config.eventUploadThreshold || 30; + this.flushIntervalMillis = +config.eventUploadPeriodMillis || 1000; + this.trackNewCampaigns = config.trackNewCampaigns || true; this.trackRevenuePerProduct = config.trackRevenuePerProduct || false; this.preferAnonymousIdForDeviceId = config.preferAnonymousIdForDeviceId || false; this.traitsToSetOnce = getTraitsToSetOnce(config); @@ -49,32 +43,20 @@ class Amplitude { } const initOptions = { - includeUtm: this.trackUtmProperties, - batchEvents: this.batchEvents, - eventUploadThreshold: this.eventUploadThreshold, - eventUploadPeriodMillis: this.eventUploadPeriodMillis, - forceHttps: this.forceHttps, - includeGclid: this.trackGclid, - includeReferrer: this.trackReferrer, - saveParamsReferrerOncePerSession: this.saveParamsReferrerOncePerSession, - deviceIdFromUrlParam: this.deviceIdFromUrlParam, - unsetParamsReferrerOnNewSession: this.unsetParamsReferrerOnNewSession, - deviceId: - this.preferAnonymousIdForDeviceId && this.analytics && this.analytics.getAnonymousId(), + attribution: { disabled: this.attribution, trackNewCampaigns: !this.trackNewCampaigns }, + flushQueueSize: this.flushQueueSize, + flushIntervalMillis: this.flushIntervalMillis, + appVersion: this.versionName, }; - window.amplitude.getInstance().init(this.apiKey, null, initOptions); - if (this.versionName) { - window.amplitude.getInstance().setVersionName(this.versionName); + if ( + navigator.userAgent.indexOf('MSIE') !== -1 || + navigator.appVersion.indexOf('Trident/') > -1 + ) { + initOptions.transport = 'xhr'; } - } - - isLoaded() { - logger.debug('in Amplitude isLoaded'); - return !!window?.amplitude?.getInstance()?.options; - } - - isReady() { - return !!window?.amplitude?.getInstance()?.options; + if (this.preferAnonymousIdForDeviceId && this.analytics) + initOptions.deviceId = this.analytics.getAnonymousId(); + window.amplitude.init(this.apiKey, null, initOptions); } identify(rudderElement) { @@ -87,7 +69,7 @@ class Amplitude { const { userId } = rudderElement.message; if (userId) { - window.amplitude.getInstance().setUserId(userId); + window.amplitude.setUserId(userId); } if (traits) { @@ -95,7 +77,6 @@ class Amplitude { Object.keys(traits).forEach(trait => { const shouldIncrement = this.traitsToIncrement.includes(trait); const shouldSetOnce = this.traitsToSetOnce.includes(trait); - if (shouldIncrement) { amplitudeIdentify.add(trait, traits[trait]); } @@ -126,7 +107,7 @@ class Amplitude { // For track products once, we will send the products in a single call. if (this.trackProductsOnce) { - if (products && type(products) === 'array') { + if (products && Array.isArray(products)) { // track all the products in a single event. const allProducts = []; @@ -154,7 +135,7 @@ class Amplitude { return; } - if (products && type(products) === 'array') { + if (products && Array.isArray(products)) { // track events iterating over product array individually. // Log the actuall event without products array. We will subsequently track each product with 'Product Purchased' event. @@ -200,7 +181,7 @@ class Amplitude { logEventAndCorrespondingRevenue(rudderMessage, dontTrackRevenue) { const { properties, event } = rudderMessage; - window.amplitude.getInstance().logEvent(event, properties); + window.amplitude.track(event, properties); if (properties.revenue && !dontTrackRevenue) { this.trackRevenue(rudderMessage); } @@ -223,7 +204,7 @@ class Amplitude { // all pages if (this.trackAllPages) { const event = 'Loaded a page'; - window.amplitude.getInstance().logEvent(event, properties); + window.amplitude.track(event, properties); } // categorized pages @@ -231,7 +212,7 @@ class Amplitude { let event; if (!useNewPageEventNameFormat) event = `Viewed page ${category}`; else event = `Viewed ${category} Page`; - window.amplitude.getInstance().logEvent(event, properties); + window.amplitude.track(event, properties); } // named pages @@ -239,7 +220,7 @@ class Amplitude { let event; if (!useNewPageEventNameFormat) event = `Viewed page ${name}`; else event = `Viewed ${name} Page`; - window.amplitude.getInstance().logEvent(event, properties); + window.amplitude.track(event, properties); } } @@ -261,10 +242,10 @@ class Amplitude { } if (groupType && groupValue) { - window.amplitude.getInstance().setGroup(groupTypeTrait, groupValueTrait); + window.amplitude.setGroup(groupTypeTrait, groupValueTrait); } else if (groupId) { // Similar as segment but not sure whether we need it as our cloud mode supports only the above if block - window.amplitude.getInstance().setGroup('[Rudderstack] Group', groupId); + window.amplitude.setGroup('[Rudderstack] Group', groupId); } // https://developers.amplitude.com/docs/setting-user-properties#setting-group-properties @@ -274,7 +255,7 @@ class Amplitude { setDeviceId(rudderElement) { const { anonymousId } = rudderElement.message; if (this.preferAnonymousIdForDeviceId && anonymousId) { - window.amplitude.getInstance().setDeviceId(anonymousId); + window.amplitude.setDeviceId(anonymousId); } } @@ -334,7 +315,7 @@ class Amplitude { delete amplitudeRevenue._properties.productId; delete amplitudeRevenue._properties.quantity; } - window.amplitude.getInstance().logRevenueV2(amplitudeRevenue); + window.amplitude.revenue(amplitudeRevenue); } getProductAttributes(product) { @@ -347,6 +328,15 @@ class Amplitude { category: product.category, }; } + + isLoaded() { + logger.debug('in Amplitude isLoaded'); + return !!(window.amplitude && window.amplitude.getDeviceId()); + } + + isReady() { + return !!(window.amplitude && window.amplitude.getDeviceId()); + } } export default Amplitude; diff --git a/packages/analytics-js-integrations/src/integrations/Amplitude/nativeSdkLoader.js b/packages/analytics-js-integrations/src/integrations/Amplitude/nativeSdkLoader.js index 4af22ad8b..da74985ab 100644 --- a/packages/analytics-js-integrations/src/integrations/Amplitude/nativeSdkLoader.js +++ b/packages/analytics-js-integrations/src/integrations/Amplitude/nativeSdkLoader.js @@ -3,111 +3,113 @@ import { LOAD_ORIGIN } from '@rudderstack/analytics-js-common/v1.1/utils/constan /* eslint-disable */ function loadNativeSdk(e, t) { + 'use strict'; var n = e.amplitude || { _q: [], _iq: {} }; - var r = t.createElement('script'); - r.type = 'text/javascript'; - r.integrity = 'sha384-5fhzC8Xw3m+x5cBag4AMKRdf900vw3AoaLty2vYfcKIX1iEsYRHZF4RLXIsu2o+F'; - r.crossOrigin = 'anonymous'; - r.async = true; - r.setAttribute('data-loader', LOAD_ORIGIN); - r.src = 'https://cdn.amplitude.com/libs/amplitude-8.21.4-min.gz.js'; - r.onload = function () { - if (!e.amplitude.runQueuedFunctions) { - console.log('[Amplitude] Error: could not load SDK'); - } - }; - var s = t.getElementsByTagName('script')[0]; - s.parentNode.insertBefore(r, s); - function i(e, t) { - e.prototype[t] = function () { - this._q.push([t].concat(Array.prototype.slice.call(arguments, 0))); - return this; - }; - } - var o = function () { - this._q = []; - return this; - }; - var a = [ - 'add', - 'append', - 'clearAll', - 'prepend', - 'set', - 'setOnce', - 'unset', - 'preInsert', - 'postInsert', - 'remove', - ]; - for (var c = 0; c < a.length; c++) { - i(o, a[c]); - } - n.Identify = o; - var l = function () { - this._q = []; - return this; - }; - var u = ['setProductId', 'setQuantity', 'setPrice', 'setRevenueType', 'setEventProperties']; - for (var p = 0; p < u.length; p++) { - i(l, u[p]); - } - n.Revenue = l; - var d = [ - 'init', - 'logEvent', - 'logRevenue', - 'setUserId', - 'setUserProperties', - 'setOptOut', - 'setVersionName', - 'setDomain', - 'setDeviceId', - 'enableTracking', - 'setGlobalUserProperties', - 'identify', - 'clearUserProperties', - 'setGroup', - 'logRevenueV2', - 'regenerateDeviceId', - 'groupIdentify', - 'onInit', - 'onNewSessionStart', - 'logEventWithTimestamp', - 'logEventWithGroups', - 'setSessionId', - 'resetSessionId', - 'getDeviceId', - 'getUserId', - 'setMinTimeBetweenSessionsMillis', - 'setEventUploadThreshold', - 'setUseDynamicConfig', - 'setServerZone', - 'setServerUrl', - 'sendEvents', - 'setLibrary', - 'setTransport', - ]; - function v(t) { - function e(e) { - t[e] = function () { - t._q.push([e].concat(Array.prototype.slice.call(arguments, 0))); + if (n.invoked) e.console && console.error && console.error('Amplitude snippet has been loaded.'); + else { + var r = function (e, t) { + e.prototype[t] = function () { + return this._q.push({ name: t, args: Array.prototype.slice.call(arguments, 0) }), this; + }; + }, + s = function (e, t, n) { + return function (r) { + e._q.push({ name: t, args: Array.prototype.slice.call(n, 0), resolve: r }); + }; + }, + o = function (e, t, n) { + e[t] = function () { + if (n) return { promise: new Promise(s(e, t, Array.prototype.slice.call(arguments))) }; + }; + }, + i = function (e) { + for (var t = 0; t < y.length; t++) o(e, y[t], !1); + for (var n = 0; n < g.length; n++) o(e, g[n], !0); }; - } - for (var n = 0; n < d.length; n++) { - e(d[n]); - } + n.invoked = !0; + var a = t.createElement('script'); + a.setAttribute('data-loader', LOAD_ORIGIN), + (a.type = 'text/javascript'), + (a.integrity = 'sha384-TPZhteUkZj8CAyBx+GZZytBdkuKnhKsSKcCoVCq0QSteWf/Kw5Kb9oVFUROLE1l3'), + (a.crossOrigin = 'anonymous'), + (a.async = !0), + (a.src = 'https://cdn.amplitude.com/libs/analytics-browser-1.9.1-min.js.gz'), + (a.onload = function () { + e.amplitude.runQueuedFunctions || console.log('[Amplitude] Error: could not load SDK'); + }); + var c = t.getElementsByTagName('script')[0]; + c.parentNode.insertBefore(a, c); + for ( + var u = function () { + return (this._q = []), this; + }, + l = [ + 'add', + 'append', + 'clearAll', + 'prepend', + 'set', + 'setOnce', + 'unset', + 'preInsert', + 'postInsert', + 'remove', + 'getUserProperties', + ], + p = 0; + p < l.length; + p++ + ) + r(u, l[p]); + n.Identify = u; + for ( + var d = function () { + return (this._q = []), this; + }, + f = [ + 'getEventProperties', + 'setProductId', + 'setQuantity', + 'setPrice', + 'setRevenue', + 'setRevenueType', + 'setEventProperties', + ], + v = 0; + v < f.length; + v++ + ) + r(d, f[v]); + n.Revenue = d; + var y = [ + 'getDeviceId', + 'setDeviceId', + 'getSessionId', + 'setSessionId', + 'getUserId', + 'setUserId', + 'setOptOut', + 'setTransport', + 'reset', + ], + g = [ + 'init', + 'add', + 'remove', + 'track', + 'logEvent', + 'identify', + 'groupIdentify', + 'setGroup', + 'revenue', + 'flush', + ]; + i(n), + (n.createInstance = function (e) { + return (n._iq[e] = { _q: [] }), i(n._iq[e]), n._iq[e]; + }), + (e.amplitude = n); } - v(n); - n.getInstance = function (e) { - e = (!e || e.length === 0 ? '$default_instance' : e).toLowerCase(); - if (!Object.prototype.hasOwnProperty.call(n._iq, e)) { - n._iq[e] = { _q: [] }; - v(n._iq[e]); - } - return n._iq[e]; - }; - e.amplitude = n; } window, document;