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 14.4 kB
{"version":3,"sources":["../src/providers/rudderstack.ts"],"names":["COOKIE_MAX_AGE_SECONDS","_RudderStack","RUDDERSTACK_KEY","onLoaded","debug","RudderAnalytics","createLogger","hostname","domain_name","domain","uuid","bytes","hex","byte","secureFlag","error","rudderstackDataplane","user_id","payload","currentUserId","current_page","platform","properties","pageProperties","event","err","RudderStack"],"mappings":"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","file":"chunk-4V72P52P.mjs","sourcesContent":["import { RudderAnalytics } from '@rudderstack/analytics-js'\nimport { rudderstackDataplane } from '../utils/urls'\nimport { createLogger } from '../utils/helpers'\n\n// Constants\nconst COOKIE_MAX_AGE_SECONDS = 180 * 24 * 60 * 60 // 180 days (~6 months)\n\n/**\n * RudderStack analytics wrapper with singleton pattern.\n * Handles user tracking, page views, and event analytics.\n */\nexport class RudderStack {\n analytics = new RudderAnalytics()\n has_identified = false\n has_initialized = false\n current_page = ''\n rudderstack_anonymous_cookie_key = 'rudder_anonymous_id'\n private static _instance: RudderStack\n private onLoadedCallback?: () => void\n private debug = false\n private log = createLogger('[RudderStack]', () => this.debug)\n\n constructor(RUDDERSTACK_KEY: string, onLoaded?: () => void, debug = false) {\n this.onLoadedCallback = onLoaded\n this.debug = debug\n this.init(RUDDERSTACK_KEY)\n }\n\n /**\n * Get or create the singleton instance of RudderStack\n * @param RUDDERSTACK_KEY - RudderStack write key\n * @param onLoaded - Optional callback when RudderStack is loaded\n * @param debug - Enable debug logging\n * @returns The RudderStack singleton instance\n */\n public static getRudderStackInstance = (\n RUDDERSTACK_KEY: string,\n onLoaded?: () => void,\n debug = false\n ): RudderStack => {\n if (!RudderStack._instance) {\n RudderStack._instance = new RudderStack(RUDDERSTACK_KEY, onLoaded, debug)\n }\n return RudderStack._instance\n }\n\n /**\n * Get the anonymous ID from cookies\n * @returns The anonymous ID or undefined if not found\n */\n getAnonymousId = (): string | undefined => {\n return document.cookie.match('(^|;)\\\\s*' + this.rudderstack_anonymous_cookie_key + '\\\\s*=\\\\s*([^;]+)')?.pop()\n }\n\n /**\n * Set anonymous ID cookie if it doesn't exist\n * Creates a secure cookie with proper domain and security attributes\n */\n setCookieIfNotExists = (): void => {\n const anonymous_id = this.getAnonymousId()\n\n if (!anonymous_id) {\n try {\n const hostname = window.location.hostname\n const external_domains = ['webflow.io']\n const is_external_domain = external_domains.some(domain => hostname.endsWith(domain))\n const domain_name = is_external_domain ? hostname : hostname.split('.').slice(-2).join('.')\n\n // Generate cryptographically secure UUID\n let uuid: string\n if (crypto?.randomUUID) {\n uuid = crypto.randomUUID()\n } else if (crypto?.getRandomValues) {\n // Fallback: Generate UUID v4 using crypto.getRandomValues\n const bytes = new Uint8Array(16)\n crypto.getRandomValues(bytes)\n // Set version (4) and variant bits\n bytes[6] = (bytes[6]! & 0x0f) | 0x40\n bytes[8] = (bytes[8]! & 0x3f) | 0x80\n // Convert to UUID string format\n const hex = Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('')\n uuid = `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`\n } else {\n // Crypto API not available - this should not happen in modern browsers\n throw new Error('Crypto API not available for secure random UUID generation')\n }\n\n const isSecure = window.location.protocol === 'https:'\n const secureFlag = isSecure ? '; Secure' : ''\n\n document.cookie = `${this.rudderstack_anonymous_cookie_key}=${uuid}; path=/; Domain=${domain_name}; max-age=${COOKIE_MAX_AGE_SECONDS}; SameSite=Lax${secureFlag}`\n } catch (error) {\n console.warn('RudderStack: Failed to set anonymous ID cookie', error)\n }\n }\n }\n\n /**\n * Get the current user ID\n * @returns The user ID, null, or undefined if not identified\n */\n getUserId = () => this.analytics.getUserId()\n\n /**\n * Initialize RudderStack with the provided key\n * @param RUDDERSTACK_KEY - RudderStack write key\n */\n init = (RUDDERSTACK_KEY: string): void => {\n if (!RUDDERSTACK_KEY) {\n console.warn('RudderStack: Initialization skipped - no key provided')\n return\n }\n\n this.log('init | loading SDK', { dataplane: rudderstackDataplane })\n\n try {\n this.setCookieIfNotExists()\n\n this.analytics.load(RUDDERSTACK_KEY, rudderstackDataplane, {\n externalAnonymousIdCookieName: this.rudderstack_anonymous_cookie_key,\n storage: { type: 'localStorage' },\n // Performance optimizations\n lockIntegrationsVersion: true,\n onLoaded: () => {\n this.has_initialized = true\n this.has_identified = !!this.getUserId()\n this.log('init | SDK loaded successfully', {\n userId: this.getUserId(),\n anonymousId: this.getAnonymousId(),\n })\n this.onLoadedCallback?.()\n },\n })\n } catch (error) {\n console.error('RudderStack: Failed to initialize', error)\n }\n }\n\n /**\n * Identify a user with RudderStack\n * Only identifies if user hasn't been identified yet\n * @param user_id - The user ID to identify\n * @param payload - Optional user traits (e.g., language, custom properties)\n */\n identifyEvent = (user_id: string, payload?: Record<string, any>): void => {\n if (!this.has_initialized) {\n console.warn('RudderStack: Cannot identify - not initialized')\n return\n }\n\n const currentUserId = this.getUserId()\n if (!currentUserId || currentUserId !== user_id) {\n try {\n this.log('identifyEvent | identifying user', { user_id, traits: payload })\n this.analytics.identify(user_id, payload || {})\n this.has_identified = true\n } catch (error) {\n console.error('RudderStack: Failed to identify user', error)\n }\n } else {\n this.log('identifyEvent | user already identified', { user_id })\n this.has_identified = true\n }\n }\n\n /**\n * Track a page view event\n * @param current_page - The page name/path\n * @param platform - The platform name (default: 'Deriv App')\n * @param user_id - The user ID\n * @param properties - Additional page properties\n */\n pageView = (\n current_page: string,\n platform = 'Deriv App',\n user_id: string,\n properties?: Record<string, unknown>\n ): void => {\n if (!this.has_initialized || current_page === this.current_page) return\n\n try {\n const pageProperties = {\n ...(user_id && { user_id }),\n ...properties,\n }\n\n this.log('pageView | tracking page view', { platform, current_page, properties: pageProperties })\n // Type assertion needed due to RudderStack's type definitions\n this.analytics.page(platform, current_page, pageProperties as any)\n this.current_page = current_page\n } catch (error) {\n console.error('RudderStack: Failed to track page view', error)\n }\n }\n\n /**\n * Reset the RudderStack instance\n * Clears user identification and resets tracking state\n */\n reset = (): void => {\n if (!this.has_initialized) return\n\n try {\n this.log('reset | resetting RudderStack session')\n this.analytics.reset()\n this.has_identified = false\n } catch (error) {\n console.error('RudderStack: Failed to reset', error)\n }\n }\n\n /**\n * Track a custom event with payload\n * Payload is pre-cleaned by analytics.ts using cleanObject before being passed here\n * @param event - The event name\n * @param payload - The event payload with core attributes\n */\n track = (event: string, payload: Record<string, any>): void => {\n if (!this.has_initialized) return\n\n try {\n this.log('track | sending event to RudderStack', { event, payload })\n // Type assertion needed to match RudderStack's ApiObject type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.analytics.track(event as string, payload as any)\n } catch (err) {\n console.warn('RudderStack: Failed to track event', err)\n }\n }\n}\n"]}