@behindthescenes/analytics 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@behindthescenes/analytics",
3
- "version": "0.0.9",
4
- "generatedAt": "2026-04-30T04:20:35.752Z",
3
+ "version": "0.0.11",
4
+ "generatedAt": "2026-04-30T04:31:52.621Z",
5
5
  "artifacts": {
6
6
  "browser": "browser/browser.js",
7
7
  "cjs": "cjs/index.js",
@@ -0,0 +1,499 @@
1
+ # Advanced Setup Guide
2
+
3
+ Advanced configuration and use cases for the BTS Analytics SDK.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Custom Endpoint](#custom-endpoint)
8
+ - [Request Signing](#request-signing)
9
+ - [Google Analytics Integration](#google-analytics-integration)
10
+ - [Attribution Control](#attribution-control)
11
+ - [SPA Configuration](#spa-configuration)
12
+ - [Custom Auto-Tracking](#custom-auto-tracking)
13
+ - [Error Handling](#error-handling)
14
+ - [Performance Optimization](#performance-optimization)
15
+ - [Privacy and Compliance](#privacy-and-compliance)
16
+
17
+ ---
18
+
19
+ ## Custom Endpoint
20
+
21
+ Override the default analytics endpoint for local development or custom proxies.
22
+
23
+ ```typescript
24
+ const analytics = createBTSAnalytics({
25
+ siteKey: "your-public-site-key",
26
+ endpoint: "https://your-proxy.com/v2/website/analytics",
27
+ });
28
+ ```
29
+
30
+ **Note:** Production use should use the default endpoint. Only override for specific development or proxy scenarios.
31
+
32
+ ---
33
+
34
+ ## Request Signing
35
+
36
+ Add custom headers for request validation and security.
37
+
38
+ ### Basic Header Addition
39
+
40
+ ```typescript
41
+ const analytics = createBTSAnalytics({
42
+ siteKey: "your-public-site-key",
43
+ requestHeaders: {
44
+ "X-Custom-Header": "value",
45
+ "X-Source": "my-website",
46
+ },
47
+ });
48
+ ```
49
+
50
+ **Important:** When `requestHeaders` is configured, the SDK uses `fetch(..., { keepalive: true })` instead of `sendBeacon` for page-unload events.
51
+
52
+ ---
53
+
54
+ ## Google Analytics Integration
55
+
56
+ ### Detection Mode (Default)
57
+
58
+ The SDK automatically detects existing GA4 installations:
59
+
60
+ ```typescript
61
+ const analytics = createBTSAnalytics({
62
+ siteKey: "your-public-site-key",
63
+ // GA detection is automatic, no configuration needed
64
+ });
65
+ ```
66
+
67
+ Detected GA data is included with every event:
68
+
69
+ ```json
70
+ {
71
+ "ga_client_id": "123456789.987654321",
72
+ "ga_tag_installed": true,
73
+ "googleAnalytics": {
74
+ "tagInstalled": true,
75
+ "clientId": "123456789.987654321",
76
+ "measurementId": "G-ABC123"
77
+ }
78
+ }
79
+ ```
80
+
81
+ ### Proxy Mode
82
+
83
+ Load GA tag for scanner visibility while forwarding events through BTS:
84
+
85
+ ```typescript
86
+ const analytics = createBTSAnalytics({
87
+ siteKey: "your-public-site-key",
88
+ googleAnalytics: {
89
+ loadTag: true,
90
+ measurementId: "G-XXXXXXXXXX",
91
+ },
92
+ });
93
+ ```
94
+
95
+ This:
96
+ 1. Loads the Google tag script with `send_page_view: false`
97
+ 2. Allows GA scanners to detect an installed tag
98
+ 3. Forwards all events server-side through BTS
99
+
100
+ ### Disable GA Detection
101
+
102
+ ```typescript
103
+ const analytics = createBTSAnalytics({
104
+ siteKey: "your-public-site-key",
105
+ googleAnalytics: false,
106
+ });
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Attribution Control
112
+
113
+ ### Understanding Attribution
114
+
115
+ The SDK automatically captures and persists:
116
+
117
+ **UTM Parameters:**
118
+ - `utm_source`, `utm_medium`, `utm_campaign`
119
+ - `utm_term`, `utm_content`
120
+
121
+ **Click IDs:**
122
+ - `fbclid`, `gclid`, `gbraid`, `wbraid`
123
+ - `li_fat_id`, `msclkid`, `ttclid`
124
+
125
+ **Cookies:**
126
+ - `_fbp`, `_fbc`
127
+
128
+ ### Attribution Data Structure
129
+
130
+ Attribution data is automatically attached to every event:
131
+
132
+ ```json
133
+ {
134
+ "attribution": {
135
+ "utm": {
136
+ "utm_source": "facebook",
137
+ "utm_medium": "paid",
138
+ "utm_campaign": "summer_sale"
139
+ },
140
+ "clickIds": {
141
+ "fbclid": "abc123",
142
+ "fbp": "fb.1.1234567890.987654321"
143
+ },
144
+ "landingUrl": "https://yoursite.com/landing?utm_source=facebook",
145
+ "referrer": "https://facebook.com"
146
+ }
147
+ }
148
+ ```
149
+
150
+ ### Custom Attribution
151
+
152
+ Add custom attribution data to specific events:
153
+
154
+ ```typescript
155
+ analytics.track("custom_campaign_click", {
156
+ attribution: {
157
+ utm: {
158
+ utm_source: "newsletter",
159
+ utm_medium: "email",
160
+ },
161
+ customCampaignId: "campaign_123",
162
+ },
163
+ });
164
+ ```
165
+
166
+ ---
167
+
168
+ ## SPA Configuration
169
+
170
+ ### React Router / Vue Router / etc.
171
+
172
+ For frameworks with client-side routing, disable automatic pageviews and handle manually:
173
+
174
+ ```typescript
175
+ const analytics = createBTSAnalytics({
176
+ siteKey: "your-public-site-key",
177
+ autoPageviews: false,
178
+ });
179
+ ```
180
+
181
+ #### React Router v6
182
+
183
+ ```tsx
184
+ import { useEffect } from "react";
185
+ import { useLocation } from "react-router-dom";
186
+
187
+ function AnalyticsRouteTracker() {
188
+ const location = useLocation();
189
+
190
+ useEffect(() => {
191
+ analytics.page(location.pathname + location.search);
192
+ }, [location]);
193
+
194
+ return null;
195
+ }
196
+ ```
197
+
198
+ #### Vue Router
199
+
200
+ ```typescript
201
+ import { watch } from "vue";
202
+ import { useRoute } from "vue-router";
203
+
204
+ const route = useRoute();
205
+
206
+ watch(
207
+ () => route.fullPath,
208
+ (fullPath) => {
209
+ analytics.page(fullPath);
210
+ },
211
+ { immediate: true }
212
+ );
213
+ ```
214
+
215
+ ### Selective Auto-Tracking
216
+
217
+ Enable only specific auto-tracking features:
218
+
219
+ ```typescript
220
+ const analytics = createBTSAnalytics({
221
+ siteKey: "your-public-site-key",
222
+ autoTrack: {
223
+ pageviews: false, // Disable - handle manually
224
+ history: false, // Disable SPA hooks
225
+ outboundLinks: true, // Enable external link tracking
226
+ buttonClicks: true, // Enable button tracking
227
+ formSubmissions: true, // Enable form tracking
228
+ search: true, // Enable search tracking
229
+ viewContent: true, // Enable content view tracking
230
+ },
231
+ });
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Custom Auto-Tracking
237
+
238
+ ### Track Specific Elements Only
239
+
240
+ Use CSS selectors or data attributes for precise tracking:
241
+
242
+ ```typescript
243
+ // Track only specific buttons
244
+ analytics.track("cta_clicked", {
245
+ buttonId: "buy-now",
246
+ section: "pricing",
247
+ });
248
+
249
+ // Track with custom attributes
250
+ document.querySelectorAll("[data-track-custom]").forEach((el) => {
251
+ el.addEventListener("click", () => {
252
+ const eventName = el.getAttribute("data-track-custom");
253
+ analytics.track(eventName, {
254
+ elementId: el.id,
255
+ context: el.getAttribute("data-context"),
256
+ });
257
+ });
258
+ });
259
+ ```
260
+
261
+ ### Dynamic Content Views
262
+
263
+ For dynamically loaded content (infinite scroll, etc.):
264
+
265
+ ```typescript
266
+ // The SDK automatically observes DOM changes via MutationObserver
267
+ // Just add the data attribute to new elements:
268
+ const newCard = document.createElement("article");
269
+ newCard.setAttribute("data-bts-view-content", `video_${videoId}`);
270
+ newCard.setAttribute("data-bts-content-type", "video");
271
+ newCard.setAttribute("data-bts-content-title", videoTitle);
272
+ container.appendChild(newCard);
273
+ // SDK will automatically start tracking visibility
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Error Handling
279
+
280
+ ### Request Errors
281
+
282
+ The SDK automatically handles network errors:
283
+
284
+ 1. Failed batches are requeued
285
+ 2. Retry is scheduled
286
+ 3. Events are preserved in memory
287
+
288
+ ### Custom Error Handling
289
+
290
+ ```typescript
291
+ // For contact form submissions
292
+ try {
293
+ await analytics.submitContactForm({
294
+ locationId: "loc-123",
295
+ email: "fan@example.com",
296
+ });
297
+ } catch (error) {
298
+ console.error("Form submission failed:", error);
299
+ // Show user-friendly error message
300
+ }
301
+
302
+ // For journey operations
303
+ try {
304
+ const { journeyToken } = await analytics.startFunnel();
305
+ } catch (error) {
306
+ console.error("Failed to start funnel:", error);
307
+ // Continue without attribution
308
+ }
309
+ ```
310
+
311
+ ### Debug Mode
312
+
313
+ Enable debug logging to troubleshoot:
314
+
315
+ ```typescript
316
+ const analytics = createBTSAnalytics({
317
+ siteKey: "your-public-site-key",
318
+ debug: true, // Logs all events and network requests
319
+ });
320
+ ```
321
+
322
+ ---
323
+
324
+ ## Performance Optimization
325
+
326
+ ### Batch Size
327
+
328
+ Events are batched automatically (flush every 300ms or 50 events). For high-traffic sites:
329
+
330
+ ```typescript
331
+ const analytics = createBTSAnalytics({
332
+ siteKey: "your-public-site-key",
333
+ flushIntervalMs: 500, // Increase interval for more batching
334
+ });
335
+ ```
336
+
337
+ ### Lazy Loading
338
+
339
+ Load the SDK only when needed:
340
+
341
+ ```typescript
342
+ // Dynamic import for code splitting
343
+ async function initAnalytics() {
344
+ const { createBTSAnalytics } = await import("@behindthescenes/analytics");
345
+ return createBTSAnalytics({
346
+ siteKey: "your-public-site-key",
347
+ });
348
+ }
349
+ ```
350
+
351
+ ### Conditional Tracking
352
+
353
+ Skip tracking for bots or specific conditions:
354
+
355
+ ```typescript
356
+ const isBot = /bot|crawler|spider/i.test(navigator.userAgent);
357
+ const isPrerender = navigator.userAgent.includes("Prerender");
358
+
359
+ if (!isBot && !isPrerender) {
360
+ const analytics = createBTSAnalytics({
361
+ siteKey: "your-public-site-key",
362
+ });
363
+ }
364
+ ```
365
+
366
+ ---
367
+
368
+ ## Privacy and Compliance
369
+
370
+ ### GDPR / CCPA Compliance
371
+
372
+ The SDK respects user privacy preferences:
373
+
374
+ ```typescript
375
+ // Check for consent before initializing
376
+ const hasConsent = localStorage.getItem("analytics_consent") === "true";
377
+
378
+ if (hasConsent) {
379
+ const analytics = createBTSAnalytics({
380
+ siteKey: "your-public-site-key",
381
+ });
382
+ } else {
383
+ // Load with minimal tracking or don't load at all
384
+ const analytics = createBTSAnalytics({
385
+ siteKey: "your-public-site-key",
386
+ autoTrack: false, // Disable all auto-tracking
387
+ });
388
+ }
389
+ ```
390
+
391
+ ### Consent Management
392
+
393
+ Integrate with your consent management platform:
394
+
395
+ ```typescript
396
+ // Example: OneTrust integration
397
+ function onConsentChange(consent) {
398
+ if (consent.analytics) {
399
+ // Initialize or re-enable analytics
400
+ window.analytics = createBTSAnalytics({
401
+ siteKey: "your-public-site-key",
402
+ });
403
+ } else {
404
+ // Destroy analytics instance
405
+ window.analytics?.destroy();
406
+ window.analytics = null;
407
+ }
408
+ }
409
+ ```
410
+
411
+ ### Data Minimization
412
+
413
+ Send only necessary data:
414
+
415
+ ```typescript
416
+ analytics.track("purchase", {
417
+ orderId: "order_123",
418
+ monetaryValue: 99,
419
+ currency: "USD",
420
+ // Don't include: user email, full name, address, etc.
421
+ });
422
+ ```
423
+
424
+ ### PII Handling
425
+
426
+ Never send personally identifiable information in tracking calls:
427
+
428
+ ```typescript
429
+ // ❌ Bad - includes PII
430
+ analytics.track("form_submit", {
431
+ email: "john@example.com",
432
+ phone: "+1234567890",
433
+ });
434
+
435
+ // ✅ Good - use userId only
436
+ analytics.identify("user_123", {
437
+ // Optional traits - keep minimal
438
+ plan: "pro",
439
+ country: "US",
440
+ });
441
+ ```
442
+
443
+ ---
444
+
445
+ ## Best Practices
446
+
447
+ ### 1. Initialize Once
448
+
449
+ Create a singleton instance and reuse:
450
+
451
+ ```typescript
452
+ // analytics.ts
453
+ import { createBTSAnalytics } from "@behindthescenes/analytics";
454
+
455
+ export const analytics = createBTSAnalytics({
456
+ siteKey: "your-public-site-key",
457
+ });
458
+ ```
459
+
460
+ ### 2. Handle Navigation Properly
461
+
462
+ For SPAs, always track route changes:
463
+
464
+ ```typescript
465
+ // In your router
466
+ router.afterEach((to) => {
467
+ analytics.page(to.fullPath);
468
+ });
469
+ ```
470
+
471
+ ### 3. Test Your Implementation
472
+
473
+ ```typescript
474
+ // Development testing
475
+ if (process.env.NODE_ENV === "development") {
476
+ window.testAnalytics = () => {
477
+ analytics.track("test_event", { timestamp: Date.now() });
478
+ analytics.flushNow();
479
+ console.log("Test event sent - check the network tab");
480
+ };
481
+ }
482
+ ```
483
+
484
+ ### 4. Monitor Event Volume
485
+
486
+ Track your event volume to avoid unexpected costs:
487
+
488
+ ```typescript
489
+ let eventCount = 0;
490
+
491
+ const originalTrack = analytics.track.bind(analytics);
492
+ analytics.track = (...args) => {
493
+ eventCount++;
494
+ if (eventCount % 100 === 0) {
495
+ console.log(`Analytics events this session: ${eventCount}`);
496
+ }
497
+ return originalTrack(...args);
498
+ };
499
+ ```