UNPKG

@deriv-com/analytics

Version:

Comprehensive analytics package for Deriv applications. Provides unified event tracking, A/B testing, and user analytics through RudderStack, PostHog and GrowthBook integrations with built-in caching and offline support.

1 lines 31.8 kB
{"version":3,"sources":["../../../src/providers/posthog.ts"],"names":["_Posthog","options","debug","createLogger","currentApiKey","currentCookieName","staleCookies","c","name","hostname","domainParts","rootDomain","domain","domainAttr","deleted","apiKey","api_host","config","posthog","resolvedApiHost","getPosthogApiHost","posthogConfig","posthogUiHost","event","eventMs","now","currentHost","allowedDomains","fns","result","fn","error","currentDistinctId","nextUserId","caller","user_id","traits","email","language","country_of_residence","alreadyIdentified","updates","isInternalEmail","event_name","properties","key","raw","entry","callback","unsubscribe","id","Posthog"],"mappings":"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","file":"index.mjs","sourcesContent":["import posthog from 'posthog-js'\nimport type { TPosthogConfig, TPosthogIdentifyTraits, TPosthogOptions } from './posthogTypes'\nimport { allowedDomains, getPosthogApiHost, posthogUiHost } from '../utils/urls'\nimport { createLogger, isInternalEmail } from '../utils/helpers'\n\n/**\n * PostHog analytics wrapper with singleton pattern.\n * Provides optional PostHog integration for event tracking and session recording.\n *\n * Features:\n * - Dynamically loads PostHog SDK on demand\n * - Domain allowlisting for security\n * - Automatic user identification with client_id enforcement\n * - client_id backfill for previously identified users via backfillPersonProperties\n * - Custom event tracking with property sanitization\n * - Built-in caching and retry mechanisms (handled by posthog-js library)\n *\n * Note: PostHog handles its own event queuing, caching, and retry logic internally.\n * No additional caching is needed at the wrapper level.\n */\nexport class Posthog {\n has_initialized = false\n has_identified = false\n private static _instance: Posthog\n // Survives re-instantiation — covers hot reload and multiple module copies.\n // posthog.__loaded is checked as a secondary guard for cases where this\n // static field is reset but posthog-js already has a live instance (e.g.\n // duplicate module bundles in micro-frontends).\n private static _hasLoaded = false\n private static readonly ILLEGAL_IDS = new Set([\n 'restored',\n 'null',\n 'undefined',\n 'anonymous',\n 'guest',\n 'distinctid',\n 'distinct_id',\n 'id',\n 'not_authenticated',\n 'email',\n 'true',\n 'false',\n '0',\n 'none',\n 'nan',\n ])\n private options: TPosthogOptions\n private debug = false\n private log = createLogger('[PostHog]', () => this.debug)\n\n constructor(options: TPosthogOptions, debug = false) {\n this.options = options\n this.debug = debug\n this.init()\n }\n\n /**\n * Get or create the singleton instance of Posthog\n * @param options - PostHog configuration options including API key\n * @param debug - Enable debug logging\n * @returns The Posthog singleton instance\n */\n public static getPosthogInstance = (options: TPosthogOptions, debug = false): Posthog => {\n if (!Posthog._instance) {\n Posthog._instance = new Posthog(options, debug)\n } else if (options.apiKey && options.apiKey !== Posthog._instance.options.apiKey) {\n console.warn('Posthog: getPosthogInstance called with a different API key — returning existing instance')\n }\n return Posthog._instance\n }\n\n /**\n * Remove stale PostHog cookies that don't belong to the current project key.\n * PostHog sets cookies named `ph_{apiKey}_posthog` — if multiple project keys\n * have been used in the same browser, old cookies pile up and should be cleaned.\n */\n private cleanupStalePosthogCookies = (currentApiKey: string): void => {\n if (typeof document === 'undefined' || typeof window === 'undefined') return\n\n const currentCookieName = `ph_${currentApiKey}_posthog`\n const staleCookies = document.cookie\n .split(';')\n .map(c => c.trim().split('=')[0] ?? '')\n .filter(name => /^ph_.+_posthog$/.test(name) && name !== currentCookieName)\n\n if (staleCookies.length === 0) return\n\n const hostname = window.location.hostname\n const domainParts = hostname.split('.')\n // TLD+2 assumption: works for deriv.com → .deriv.com but would produce\n // .co.uk for app.deriv.co.uk. Acceptable for current Deriv domains.\n const rootDomain = domainParts.length >= 2 ? `.${domainParts.slice(-2).join('.')}` : hostname\n\n staleCookies.forEach(name => {\n // Try deleting with root domain, subdomain, and no domain\n ;[rootDomain, hostname, ''].forEach(domain => {\n const domainAttr = domain ? `; Domain=${domain}` : ''\n document.cookie = `${name}=; path=/${domainAttr}; max-age=0; SameSite=Lax`\n })\n const deleted = !document.cookie.split(';').some(c => c.trim().startsWith(`${name}=`))\n this.log(`cleanupStalePosthogCookies | ${deleted ? 'removed' : 'failed to remove'} stale cookie: ${name}`)\n })\n }\n\n /**\n * Initialize PostHog with configuration\n * Configures PostHog instance with provided options\n */\n init = (): void => {\n try {\n const { apiKey, api_host, config = {} } = this.options\n\n if (!apiKey) {\n console.warn('Posthog: No API key provided')\n return\n }\n\n if (Posthog._hasLoaded || (posthog as any).__loaded) {\n this.log('init | PostHog already initialized, skipping re-init')\n this.has_initialized = true\n return\n }\n\n this.cleanupStalePosthogCookies(apiKey)\n\n const resolvedApiHost = api_host || getPosthogApiHost()\n this.log('init | loading PostHog SDK', { api_host: resolvedApiHost })\n\n const posthogConfig: TPosthogConfig = {\n // Overridable defaults — consumers can override these via config\n api_host: resolvedApiHost,\n ui_host: posthogUiHost,\n // Scope autocapture to clicks only. Default also captures input changes and\n // form submissions which, on a high-frequency trading SPA, contributes to\n // burst-limit hits.\n autocapture: { dom_event_allowlist: ['click'] },\n // Pin rate limits explicitly so SDK default changes don't silently affect us.\n rate_limiting: {\n events_per_second: 10,\n events_burst_limit: 100,\n },\n ...config,\n\n // ── Enforced after consumer spread ─────────────────────────────────────\n person_profiles: 'identified_only',\n // 'history_change' fires $pageview on every pushState/replaceState (SPA-friendly).\n // Consumers must NOT also call posthog.capture('$pageview') manually — that\n // causes a duplicate on every navigation and hits the burst rate limit.\n capture_pageview: 'history_change',\n capture_pageleave: true,\n session_recording: {\n ...config.session_recording,\n recordCrossOriginIframes: true,\n minimumDurationMilliseconds: 30000,\n maskAllInputs: true,\n },\n before_send: event => {\n // SSR guard — note: this drops all server-side events.\n // If consumers ever use SSR (Next.js, Nuxt), move domain check\n // to runtime and remove the window guard from the timestamp filter.\n if (typeof window === 'undefined' || !event) return null\n\n if (event.timestamp) {\n const sevenDaysMs = 7 * 24 * 60 * 60 * 1000\n const eventMs = event.timestamp.getTime()\n const now = Date.now()\n if (eventMs < now - sevenDaysMs || eventMs > now + sevenDaysMs) {\n this.log('init | before_send dropped event with bad timestamp', {\n event: event.event,\n timestamp: event.timestamp.toISOString(),\n })\n return null\n }\n }\n\n const currentHost = window.location.hostname\n if (currentHost !== 'localhost' && currentHost !== '127.0.0.1') {\n const isAllowed = allowedDomains.some(\n domain => currentHost.endsWith(`.${domain}`) || currentHost === domain\n )\n if (!isAllowed) {\n this.log('init | before_send blocked event from disallowed host', { currentHost })\n return null\n }\n }\n\n if (config.before_send) {\n const fns = Array.isArray(config.before_send) ? config.before_send : [config.before_send]\n let result: typeof event | null = event\n for (const fn of fns) {\n result = result ? fn(result) : null\n }\n return result\n }\n return event\n },\n }\n\n // Initialize PostHog\n posthog.init(apiKey, posthogConfig)\n Posthog._hasLoaded = true\n this.has_initialized = true\n this.log('init | PostHog SDK loaded successfully')\n } catch (error) {\n console.error('Posthog: Failed to initialize', error)\n }\n }\n\n private static isAnonymousId = (id: string | undefined | null): boolean => {\n if (!id) return true\n // Hard-coded UUID v4 pattern — matches posthog-js anonymous ID format.\n // Verify after major posthog-js version bumps; a changed format would treat\n // new anonymous IDs as identified and trigger spurious resets on every login.\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id)\n }\n\n private resetIfStaleId = (\n currentDistinctId: string | undefined | null,\n nextUserId: string,\n caller: string\n ): void => {\n if (!Posthog.isAnonymousId(currentDistinctId)) {\n this.log(`${caller} | stale identified user, resetting`, {\n previous: currentDistinctId,\n next: nextUserId,\n })\n posthog.reset()\n }\n }\n\n /**\n * Identify a user with PostHog.\n * Skipped if the user is already identified — use backfillPersonProperties to backfill\n * client_id for users identified in previous sessions.\n *\n * @param user_id - The user ID to identify\n * @param traits - User properties (language, country_of_residence, etc.)\n */\n identifyEvent = (user_id: string, traits: TPosthogIdentifyTraits = {}): void => {\n if (!this.has_initialized) {\n console.warn('Posthog: Cannot identify - not initialized')\n return\n }\n\n try {\n if (!user_id || !user_id.trim() || Posthog.ILLEGAL_IDS.has(user_id.toLowerCase())) {\n this.log('identifyEvent | skipped — invalid user_id', { user_id })\n return\n }\n\n const currentDistinctId = posthog.get_distinct_id()\n\n if (currentDistinctId === user_id) {\n this.log('identifyEvent | skipped — user already identified', { user_id })\n return\n }\n\n // If PostHog holds a different identified user's ID (not an anonymous UUID),\n // reset first to prevent profile merging between accounts.\n this.resetIfStaleId(currentDistinctId, user_id, 'identifyEvent')\n\n this.log('identifyEvent | identifying user', { user_id, traits })\n posthog.identify(user_id, {\n ...traits,\n client_id: user_id,\n })\n this.has_identified = true\n } catch (error) {\n console.error('Posthog: Failed to identify user', error)\n }\n }\n\n /**\n * Reset PostHog state\n * Clears user identification and resets the instance\n */\n reset = (): void => {\n if (!this.has_initialized) return\n\n try {\n this.log('reset | resetting PostHog session')\n posthog.reset()\n this.has_identified = false\n } catch (error) {\n console.error('Posthog: Failed to reset', error)\n }\n }\n\n /**\n * Ensure client_id is set in PostHog stored person properties.\n * Call this when the user ID is available and PostHog is loaded.\n * No-op if client_id is already present.\n *\n * @param params.user_id - The user ID to use as client_id\n * @param params.email - The user's email, used to determine is_internal\n * @param params.language - The user's language (BCP 47 tag, e.g. \"en-GB\")\n * @param params.country_of_residence - The user's country of residence\n */\n backfillPersonProperties = ({\n user_id,\n email,\n language,\n country_of_residence,\n }: {\n user_id: string\n email?: string\n language?: string\n country_of_residence?: string\n }): void => {\n if (!this.has_initialized || !user_id) return\n\n if (!user_id.trim() || Posthog.ILLEGAL_IDS.has(user_id.toLowerCase())) {\n this.log('backfillPersonProperties | skipped — invalid user_id', { user_id })\n return\n }\n\n try {\n const currentDistinctId = posthog.get_distinct_id()\n const alreadyIdentified = currentDistinctId === user_id\n\n // Reset stale identity FIRST — otherwise property reads below see the previous\n // user's cached values and we may early-return without identifying the new user.\n if (!alreadyIdentified) {\n this.resetIfStaleId(currentDistinctId, user_id, 'backfillPersonProperties')\n }\n\n const updates: Record<string, any> = {}\n\n // Falsy is correct for string-valued properties; '' is not a valid value and also warrants a rewrite.\n // is_internal uses == null because false is a legitimate value that must not be overwritten.\n if (!posthog.get_property('client_id')) {\n updates.client_id = user_id\n }\n if (email && posthog.get_property('is_internal') == null) {\n updates.is_internal = isInternalEmail(email)\n }\n if (language && !posthog.get_property('language')) {\n updates.language = language\n }\n if (country_of_residence && !posthog.get_property('country_of_residence')) {\n updates.country_of_residence = country_of_residence\n }\n\n if (alreadyIdentified) {\n if (Object.keys(updates).length === 0) {\n this.log('backfillPersonProperties | skipped — all properties already present', { user_id })\n return\n }\n this.log('backfillPersonProperties | backfilling person properties', { user_id, updates })\n posthog.setPersonProperties(updates)\n } else {\n // Always identify after a potential reset — ensures client_id lands even if persistence was cleared.\n if (!updates.client_id) updates.client_id = user_id\n this.log('backfillPersonProperties | user not identified, identifying now', { user_id, updates })\n posthog.identify(user_id, updates)\n this.has_identified = true\n }\n } catch (error) {\n console.error('Posthog: Failed to backfill person properties', error)\n }\n }\n\n /**\n * Capture a custom event with properties\n * Properties are pre-flattened and cleaned by analytics.ts before being passed here\n *\n * @param event_name - The name of the event to track\n * @param properties - Event properties including core attributes (already flattened and cleaned)\n */\n capture = (event_name: string, properties?: Record<string, any>): void => {\n if (!this.has_initialized) return\n\n try {\n this.log('capture | sending event to PostHog', { event_name, properties })\n posthog.capture(event_name, properties)\n } catch (error) {\n console.error('Posthog: Failed to capture event', error)\n }\n }\n\n /**\n * Check whether a feature flag is enabled for the current user.\n *\n * @param key - The feature flag key\n * @returns true/false, or undefined if PostHog is not ready\n */\n isFeatureEnabled = (key: string): boolean | undefined => {\n if (!this.has_initialized) return undefined\n\n try {\n const result = posthog.isFeatureEnabled(key)\n this.log('isFeatureEnabled', { key, result })\n return result\n } catch (error) {\n console.error('Posthog: Failed to check feature flag', error)\n return undefined\n }\n }\n\n /**\n * Get the value of a feature flag.\n * Returns a string variant for multivariate flags, true/false for boolean flags,\n * or undefined if the flag does not exist or PostHog is not ready.\n *\n * @param key - The feature flag key\n */\n getFeatureFlag = (key: string): string | boolean | undefined => {\n if (!this.has_initialized) return undefined\n\n try {\n const result = posthog.getFeatureFlag(key)\n this.log('getFeatureFlag', { key, result })\n return result\n } catch (error) {\n console.error('Posthog: Failed to get feature flag', error)\n return undefined\n }\n }\n\n /**\n * Get the JSON payload associated with a feature flag.\n * Payloads allow attaching structured metadata (e.g. config objects) to a flag.\n *\n * @param key - The feature flag key\n */\n getFeatureFlagPayload = (\n key: string\n ): string | number | boolean | null | Record<string, unknown> | unknown[] | undefined => {\n if (!this.has_initialized) return undefined\n\n try {\n const result = posthog.getFeatureFlagResult(key)?.payload as\n | string\n | number\n | boolean\n | null\n | Record<string, unknown>\n | unknown[]\n | undefined\n this.log('getFeatureFlagPayload', { key, result })\n return result\n } catch (error) {\n console.error('Posthog: Failed to get feature flag payload', error)\n return undefined\n }\n }\n\n /**\n * Get all currently active feature flags and their values.\n *\n * @returns A map of flag key → value (boolean or string variant)\n */\n getAllFlags = (): Record<string, string | boolean> => {\n if (!this.has_initialized) return {}\n\n try {\n // NOTE: featureFlags and getFlagVariants() are internal posthog-js APIs.\n // Verify after major SDK version bumps.\n const raw = posthog.featureFlags?.getFlagVariants() ?? {}\n // FeatureFlagValue includes null/undefined for disabled/unresolved flags;\n // filter them out to honour the declared return type.\n const result = Object.fromEntries(\n Object.entries(raw).filter((entry): entry is [string, string | boolean] => entry[1] != null)\n )\n this.log('getAllFlags', { result })\n return result\n } catch (error) {\n console.error('Posthog: Failed to get all feature flags', error)\n return {}\n }\n }\n\n /**\n * Subscribe to feature flag changes.\n * The callback fires immediately with the current flags and again whenever they are reloaded.\n *\n * @param callback - Receives the list of active flag keys and a map of key → variant\n * @returns An unsubscribe function — call it to stop listening\n */\n onFeatureFlags = (\n callback: (flags: string[], variants: Record<string, string | boolean>) => void\n ): (() => void) => {\n if (!this.has_initialized) return () => {}\n\n try {\n this.log('onFeatureFlags | subscribing to feature flag changes')\n const unsubscribe = posthog.onFeatureFlags(callback)\n return typeof unsubscribe === 'function' ? unsubscribe : () => {}\n } catch (error) {\n console.error('Posthog: Failed to subscribe to feature flags', error)\n return () => {}\n }\n }\n\n /**\n * Force PostHog to reload feature flags from the server.\n * Useful after login, logout, or any attribute change that may affect targeting.\n */\n reloadFeatureFlags = (): void => {\n if (!this.has_initialized) return\n\n try {\n this.log('reloadFeatureFlags | reloading feature flags')\n posthog.reloadFeatureFlags()\n } catch (error) {\n console.error('Posthog: Failed to reload feature flags', error)\n }\n }\n}\n"]}