customerio.ts57 lines · main
| 1 | import 'server-only' |
| 2 | |
| 3 | export interface CustomerIOConfig { |
| 4 | siteId: string |
| 5 | apiKey: string |
| 6 | } |
| 7 | |
| 8 | export class CustomerIOClient { |
| 9 | private baseUrl = 'https://track.customer.io/api/v1' |
| 10 | private auth: string |
| 11 | |
| 12 | constructor(config: CustomerIOConfig) { |
| 13 | if (!config.siteId) throw new Error('CustomerIOClient: siteId is required') |
| 14 | if (!config.apiKey) throw new Error('CustomerIOClient: apiKey is required') |
| 15 | |
| 16 | this.auth = btoa(`${config.siteId}:${config.apiKey}`) |
| 17 | } |
| 18 | |
| 19 | private async makeRequest( |
| 20 | endpoint: string, |
| 21 | method: 'GET' | 'POST' | 'PUT', |
| 22 | body?: unknown |
| 23 | ): Promise<void> { |
| 24 | const response = await fetch(`${this.baseUrl}${endpoint}`, { |
| 25 | method, |
| 26 | headers: { |
| 27 | Authorization: `Basic ${this.auth}`, |
| 28 | 'Content-Type': 'application/json', |
| 29 | }, |
| 30 | body: body ? JSON.stringify(body) : undefined, |
| 31 | }) |
| 32 | |
| 33 | if (!response.ok) { |
| 34 | const errorText = await response.text() |
| 35 | throw new Error(`Customer.io API request failed: ${response.status} - ${errorText}`) |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | async identify(email: string, attributes: Record<string, unknown> = {}): Promise<void> { |
| 40 | await this.makeRequest(`/customers/${encodeURIComponent(email)}`, 'PUT', { |
| 41 | email, |
| 42 | ...attributes, |
| 43 | }) |
| 44 | } |
| 45 | |
| 46 | async track( |
| 47 | email: string, |
| 48 | event: string, |
| 49 | properties: Record<string, unknown> = {} |
| 50 | ): Promise<void> { |
| 51 | await this.makeRequest(`/customers/${encodeURIComponent(email)}/events`, 'POST', { |
| 52 | name: event, |
| 53 | data: properties, |
| 54 | timestamp: Math.floor(Date.now() / 1000), |
| 55 | }) |
| 56 | } |
| 57 | } |