diff options
Diffstat (limited to 'packages/instant/src/util/heap.ts')
-rw-r--r-- | packages/instant/src/util/heap.ts | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/packages/instant/src/util/heap.ts b/packages/instant/src/util/heap.ts new file mode 100644 index 000000000..78ec3b3cc --- /dev/null +++ b/packages/instant/src/util/heap.ts @@ -0,0 +1,113 @@ +import { ObjectMap } from '@0x/types'; +import { logUtils } from '@0x/utils'; +import * as _ from 'lodash'; + +import { HEAP_ANALYTICS_ID } from '../constants'; + +import { AnalyticsEventOptions, AnalyticsUserOptions } from './analytics'; + +export interface HeapAnalytics { + loaded: boolean; + appid: string; + identify(id: string, idType: string): void; + track(eventName: string, eventProperties?: ObjectMap<string | number>): void; + resetIdentity(): void; + addUserProperties(properties: AnalyticsUserOptions): void; + addEventProperties(properties: AnalyticsEventOptions): void; + removeEventProperty(property: string): void; + clearEventProperties(): void; +} +interface ModifiedWindow { + heap?: HeapAnalytics; + zeroExInstantLoadedHeap?: boolean; +} +const getWindow = (): ModifiedWindow => { + return window as ModifiedWindow; +}; + +const setupZeroExInstantHeap = () => { + if (_.isUndefined(HEAP_ANALYTICS_ID)) { + return; + } + + const curWindow = getWindow(); + // Set property to specify that this is zeroEx's heap + curWindow.zeroExInstantLoadedHeap = true; + + // Typescript-compatible version of https://docs.heapanalytics.com/docs/installation + /* tslint:disable */ + ((window as any).heap = (window as any).heap || []), + ((window as any).heap.load = function(e: any, t: any) { + ((window as any).heap.appid = e), ((window as any).heap.config = t = t || {}); + var r = t.forceSSL || 'https:' === (document.location as Location).protocol, + a = document.createElement('script'); + (a.type = 'text/javascript'), + (a.async = !0), + (a.src = (r ? 'https:' : 'http:') + '//cdn.heapanalytics.com/js/heap-' + e + '.js'); + var n = document.getElementsByTagName('script')[0]; + (n.parentNode as Node).insertBefore(a, n); + for ( + var o = function(e: any) { + return function() { + (window as any).heap.push([e].concat(Array.prototype.slice.call(arguments, 0))); + }; + }, + p = [ + 'addEventProperties', + 'addUserProperties', + 'clearEventProperties', + 'identify', + 'resetIdentity', + 'removeEventProperty', + 'setEventProperties', + 'track', + 'unsetEventProperty', + ], + c = 0; + c < p.length; + c++ + ) + (window as any).heap[p[c]] = o(p[c]); + }); + (window as any).heap.load(HEAP_ANALYTICS_ID); + /* tslint:enable */ + + return curWindow.heap as HeapAnalytics; +}; + +export const heapUtil = { + getHeap: (): HeapAnalytics | undefined => { + const curWindow = getWindow(); + const hasOtherExistingHeapIntegration = curWindow.heap && !curWindow.zeroExInstantLoadedHeap; + if (hasOtherExistingHeapIntegration) { + return undefined; + } + + const zeroExInstantHeapIntegration = curWindow.zeroExInstantLoadedHeap && curWindow.heap; + if (zeroExInstantHeapIntegration) { + return zeroExInstantHeapIntegration; + } + + return setupZeroExInstantHeap(); + }, + evaluateHeapCall: (heapFunctionCall: (heap: HeapAnalytics) => void): void => { + if (_.isUndefined(HEAP_ANALYTICS_ID)) { + return; + } + + const curHeap = heapUtil.getHeap(); + if (curHeap) { + try { + if (curHeap.appid !== HEAP_ANALYTICS_ID) { + // Integrator has included heap after us and reset the app id + return; + } + heapFunctionCall(curHeap); + } catch (e) { + // We never want analytics to crash our React component + // TODO(sk): error reporter here + logUtils.log('Analytics error', e); + } + } + }, +}; |