UNPKG

@gitlab/application-sdk-browser

Version:

Client side Browser SDK for GitLab Application services

260 lines (230 loc) 6.49 kB
import { newTracker, enableActivityTracking, trackSelfDescribingEvent, trackPageView, setUserId, addGlobalContexts, disableAnonymousTracking, BrowserTracker, PageViewEvent, CommonEventProperties, setCustomUrl as _setCustomUrl, setReferrerUrl as _setReferrerUrl, setDocumentTitle as _setDocumentTitle, } from '@snowplow/browser-tracker'; import { enableLinkClickTracking, refreshLinkClickTracking as _refreshLinkClickTracking, } from '@snowplow/browser-plugin-link-click-tracking'; import { enableErrorTracking, trackError as _trackError, } from '@snowplow/browser-plugin-error-tracking'; import { isEmpty } from './utils/isEmpty'; import { doNotTrackEnabled } from './utils/doNotTrack'; import { SCHEMAS, DEFAULT_TRACKER_ID, DEFAULT_PAGEPING_OPTIONS, } from './utils/constants'; import { getSnowplowOptions } from './utils/getSnowplowOptions'; import { AllowedPlugins, GitLabClientSDKOptions, ErrorEventProperties, GitLabClientSDKType, } from './types'; export function glClientSDK( options: GitLabClientSDKOptions ): GitLabClientSDKType { return new GitLabClientSDK(options); } class GitLabClientSDK { snowplow: BrowserTracker | null = null; options: GitLabClientSDKOptions = { appId: '', host: '', hasCookieConsent: false, trackerId: DEFAULT_TRACKER_ID, pagePingTracking: true, }; defaultPlugins: AllowedPlugins = { clientHints: true, linkTracking: true, performanceTiming: true, errorTracking: true, }; constructor(options: GitLabClientSDKOptions) { this.options = { ...this.options, ...options }; this.options.plugins = { ...this.defaultPlugins, ...(options?.plugins ?? {}), }; if (!this.trackingEnabled) return; const { appId, host, hasCookieConsent = false, trackerId = DEFAULT_TRACKER_ID, pagePingTracking, plugins, } = this.options; if (!appId) { console.warn('GitLab: No appId was provided'); return; } if (!host) { console.warn('GitLab: No host was provided'); return; } /** * Initialize Snowplow Client with options */ const snowplowOptions = getSnowplowOptions( appId, hasCookieConsent, plugins ); this.snowplow = newTracker(trackerId, host, snowplowOptions) || null; if (typeof pagePingTracking === 'boolean' && pagePingTracking) { // Enables page activity tracking (sends page pings to the Collector regularly) with default options. enableActivityTracking(DEFAULT_PAGEPING_OPTIONS); } else if (typeof pagePingTracking === 'object') { // Override default settings enableActivityTracking({ minimumVisitLength: pagePingTracking.minimumVisitLength ?? DEFAULT_PAGEPING_OPTIONS.minimumVisitLength, heartbeatDelay: pagePingTracking.heartbeatDelay ?? DEFAULT_PAGEPING_OPTIONS.heartbeatDelay, }); } /** enable required plugins */ const { linkTracking, errorTracking } = plugins; if (linkTracking) { enableLinkClickTracking(); } if (errorTracking) { enableErrorTracking(); } } private get trackingEnabled(): boolean { return !doNotTrackEnabled(); } /** * Track the user defined custom event * * @param {eventName} eventName - Name of the custom event * @param {eventAttributes} eventAttributes - Additional information for custom event * @returns {void} */ public track( eventName: string, { ...eventAttributes }: Record<string, any> = ({} = {}) ): void { if (!this.trackingEnabled) return; trackSelfDescribingEvent({ event: { schema: SCHEMAS.CUSTOM_EVENT, data: { name: eventName, props: { ...eventAttributes }, }, }, }); } /** * enableLinkClickTracking only tracks clicks on links which exist when the page has loaded. * If new links can be added to the page after then which you wish to track, * just use refreshLinkClickTracking. */ public refreshLinkClickTracking = _refreshLinkClickTracking.bind(this); /** * Send error as self-describing event * * @param errorAttributes - The event information * @returns {void} */ public trackError({ ...errorAttributes }: ErrorEventProperties & CommonEventProperties): void { if (!this.trackingEnabled) return; // if error tracking plugin is not enabled, do not capture the error if (!this.options.plugins?.errorTracking) { console.warn('GitLab: Error tracking plugin is not enabled'); return; } _trackError({ ...errorAttributes }); } /** * Set cookie consent */ addCookieConsent() { disableAnonymousTracking({ stateStorageStrategy: 'cookieAndLocalStorage', }); } /** * Tracks the page views * * @param {event} event - The page view event. * @returns {void} */ public page(event?: PageViewEvent & CommonEventProperties): void { if (!this.trackingEnabled) return; trackPageView(event); } /** * Set the business defined userId and other user attributes * * @param {userId} userId - The business-defined user ID * @param {userAttributes} userAttributes - The business-defined user attributes * @returns {void} */ public identify( userId: string, userAttributes: Record<string, any> = ({} = {}) ): void { if (!this.trackingEnabled) return; setUserId(userId); if (!isEmpty(userAttributes)) { let userContext = { schema: SCHEMAS.USER_CONTEXT, data: userAttributes, }; addGlobalContexts([userContext]); } } /** * Sets a custom URL for the current page view event. * * @param {string} url - The custom URL to set. * @returns {void} */ public setCustomUrl(url: string): void { if (!this.trackingEnabled) return; _setCustomUrl(url); } /** * Sets a referrer URL for the current page view event. * * @param {string} url - The referrer URL to set. * @returns {void} */ public setReferrerUrl(url: string): void { if (!this.trackingEnabled) return; _setReferrerUrl(url); } /** * Sets a Document title which will be used as override * * @param {string} url - The referrer URL to set. * @returns {void} */ public setDocumentTitle(title: string): void { if (!this.trackingEnabled) return; _setDocumentTitle(title); } }