diff --git a/packages/analytics-client/src/analytics-client.ts b/packages/analytics-client/src/analytics-client.ts index edcf576..3cc44c3 100644 --- a/packages/analytics-client/src/analytics-client.ts +++ b/packages/analytics-client/src/analytics-client.ts @@ -36,6 +36,7 @@ export class AnalyticsClient { scrollTracking: { enabled: false }, trackResizes: false, resizeDebounceMs: 1000, + writeKey: undefined, ...config, }; @@ -180,7 +181,10 @@ export class AnalyticsClient { try { await fetch(`${this.config.apiBaseUrl}/analytics/track/interaction`, { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + ...(this.config.writeKey ? { 'X-Write-Key': this.config.writeKey } : {}), + }, body: JSON.stringify({ events }), }); @@ -227,12 +231,13 @@ export class AnalyticsClient { } private async sendViewEvents(events: ViewEventData[]): Promise { + const headers: Record = { 'Content-Type': 'application/json' }; + if (this.config.writeKey) headers['X-Write-Key'] = this.config.writeKey; + for (const event of events) { await fetch(`${this.config.apiBaseUrl}/analytics/track/view`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers, body: JSON.stringify(event), }); } @@ -241,12 +246,13 @@ export class AnalyticsClient { private async sendEngagementEvents( events: EngagementEventData[], ): Promise { + const headers: Record = { 'Content-Type': 'application/json' }; + if (this.config.writeKey) headers['X-Write-Key'] = this.config.writeKey; + for (const event of events) { await fetch(`${this.config.apiBaseUrl}/analytics/track/engagement`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers, body: JSON.stringify(event), }); } diff --git a/packages/analytics-client/src/backend-client.ts b/packages/analytics-client/src/backend-client.ts index 50b6def..2bda75f 100644 --- a/packages/analytics-client/src/backend-client.ts +++ b/packages/analytics-client/src/backend-client.ts @@ -6,6 +6,8 @@ import type { export interface BackendAnalyticsConfig { apiBaseUrl: string; appName: string; + /** Write key sent as X-Write-Key header for collector authentication. Required in production. */ + writeKey?: string; enableDebugLogging?: boolean; } @@ -19,6 +21,7 @@ export class BackendAnalyticsClient { constructor(config: BackendAnalyticsConfig) { this.config = { enableDebugLogging: false, + writeKey: undefined, ...config, }; } @@ -102,13 +105,13 @@ export class BackendAnalyticsClient { private async sendEvent(type: 'view' | 'engagement', data: ViewEventData | EngagementEventData): Promise { const endpoint = type === 'view' ? '/analytics/track/view' : '/analytics/track/engagement'; + const headers: Record = { 'Content-Type': 'application/json' }; + if (this.config.writeKey) headers['X-Write-Key'] = this.config.writeKey; try { const response = await fetch(`${this.config.apiBaseUrl}${endpoint}`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers, body: JSON.stringify(data), signal: AbortSignal.timeout(5000), // 5 second timeout }); diff --git a/packages/analytics-client/src/types.ts b/packages/analytics-client/src/types.ts index b6b7e7f..5927436 100644 --- a/packages/analytics-client/src/types.ts +++ b/packages/analytics-client/src/types.ts @@ -42,6 +42,8 @@ export interface ScrollTrackingConfig { export interface AnalyticsConfig { apiBaseUrl: string appName: string + /** Write key sent as X-Write-Key header for collector authentication. Required in production. */ + writeKey?: string batchSize?: number batchInterval?: number enableDebugLogging?: boolean