import { BaseGather, EventMeta, PageMeta, ScreenMeta, UserMeta, ConfigMeta } from './base' import { loadGTag, warn } from '../utils' declare global { interface Window { dataLayer?: Record[] } } export interface GoogleGatherOptions { id: string } // Vendor Docs: https://developers.google.com/analytics/devguides/collection/gtagjs export class GoogleGather extends BaseGather { public name = 'google' private static VENDOR_NAMESPACE = 'gtag' constructor(private options: GoogleGatherOptions) { super() } public async init(): Promise { await loadGTag(this.options.id) this.registerGlobals() this.$vendor = window[GoogleGather.VENDOR_NAMESPACE] this.config({ send_page_view: false }) this.tagCalled = true } private registerGlobals() { const globalObjectName = GoogleGather.VENDOR_NAMESPACE const globalDataLayerName = 'dataLayer' if (window[globalObjectName] == null) { window[globalDataLayerName] = window[globalDataLayerName] || [] window[globalObjectName] = function () { window[globalDataLayerName]?.push(arguments) } } window[globalObjectName]('js', new Date()) } public setUser(userMeta: UserMeta) { const { id } = userMeta this.config({ user_id: id }) } public query(...args: any) { if (!this.$vendor) { return warn(`${GoogleGather.VENDOR_NAMESPACE} was undefined`) } this.$vendor(...args) return { type: args[0], id: args[1], params: args[2] } } public config(configMeta: ConfigMeta) { return this.query('config', this.options.id, configMeta) } public event(eventMeta: EventMeta) { const { action, category, page, label, ...params } = eventMeta const eventParams = { event_category: category || page, event_label: label || JSON.stringify(params || {}, null, 2) } return this.query('event', action, eventParams) } public page(pageMeta: PageMeta) { const pageParams = { page_title: pageMeta.title || document.title, page_location: pageMeta.href || location.href, page_path: pageMeta.path || location.pathname, send_page_view: true } return this.query('event', 'page_view', pageParams) } public screen(screenMeta: ScreenMeta) { const screenParams = { screen_name: screenMeta.name } if (screenMeta.app) { screenParams['app_name'] = screenMeta.app } return this.query('event', 'screen_view', screenParams) } }