@heartbeep/beeper
Version:
Modern JavaScript SDK for Heartbeep event tracking - beep beep!
1 lines • 6.29 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts"],"names":["Heartbeep","config","apiUrl","item","data","payload","error","event","name","metadata","beep"],"mappings":"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","file":"index.mjs","sourcesContent":["import type {\n HeartbeepConfig,\n EventType,\n TrackEventData,\n TrackEventPayload,\n} from \"./types\";\n\nexport * from \"./types\";\n\nexport class Heartbeep {\n private config: HeartbeepConfig;\n private queue: Array<{ event: EventType; payload?: TrackEventPayload }> = [];\n private isReady = false;\n\n constructor(config: HeartbeepConfig) {\n if (!config.siteId) {\n throw new Error(\"[Heartbeep] siteId is required\");\n }\n\n // Build the API URL\n let apiUrl = config.apiUrl || 'https://heartbeep.live/api/beep/website';\n // Remove trailing slash\n apiUrl = apiUrl.replace(/\\/$/, '');\n // Append siteId if not already included\n if (!apiUrl.includes(config.siteId)) {\n apiUrl = `${apiUrl}/${config.siteId}`;\n }\n\n this.config = {\n ...config,\n apiUrl,\n debug: config.debug || false,\n };\n\n // Initialize when DOM is ready\n if (typeof window !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", () => this.init());\n } else {\n this.init();\n }\n }\n }\n\n private init(): void {\n this.isReady = true;\n this.processQueue();\n\n if (this.config.debug) {\n console.log(\"[Heartbeep] Initialized with siteId:\", this.config.siteId);\n }\n }\n\n private processQueue(): void {\n while (this.queue.length > 0) {\n const item = this.queue.shift();\n if (item) {\n this.track(item.event, item.payload);\n }\n }\n }\n\n private async send(data: TrackEventData): Promise<void> {\n if (this.config.debug) {\n console.log(\"[Heartbeep] Tracking event:\", data);\n }\n\n try {\n const payload = JSON.stringify(data);\n\n // Try sendBeacon first for reliability\n if (typeof navigator !== \"undefined\" && navigator.sendBeacon) {\n const sent = navigator.sendBeacon(this.config.apiUrl!, payload);\n if (sent) return;\n }\n\n // Fallback to fetch\n if (typeof fetch !== \"undefined\") {\n await fetch(this.config.apiUrl!, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: payload,\n keepalive: true,\n });\n }\n } catch (error) {\n if (this.config.debug) {\n console.error(\"[Heartbeep] Error tracking event:\", error);\n }\n }\n }\n\n track(event: EventType, payload?: TrackEventPayload): void {\n // Queue events if not ready\n if (!this.isReady) {\n this.queue.push({ event, payload });\n return;\n }\n\n // Skip tracking if running on server\n if (typeof window === \"undefined\") {\n return;\n }\n\n const data: TrackEventData = {\n event,\n name: payload?.name || document.title,\n url: window.location.href,\n timestamp: Date.now(),\n metadata: payload?.metadata,\n };\n\n this.send(data);\n }\n\n // Convenience method for pageview tracking\n pageview(name?: string): void {\n this.track(\"pageview\", { name });\n }\n\n // Convenience method for click tracking\n click(name: string, metadata?: Record<string, any>): void {\n this.track(\"click\", { name, metadata });\n }\n\n // Convenience method for purchase tracking\n purchase(name: string, metadata?: Record<string, any>): void {\n this.track(\"purchase\", { name, metadata });\n }\n}\n\n// Convenience beep function for quick tracking\nexport function beep(event: EventType, name?: string): void {\n console.log(`[Beeper] 🔔 ${event}: ${name || \"unnamed event\"}`);\n}\n"]}