Integrations Overview
Integrations Collection
Multi-provider analytics with PostHog, Segment, and Vercel. Tree-shaking optimized with retry logic, privacy controls, and batching. Single API for all analytics providers.
Quick Start
Add analytics in 3 minutes:
pnpm add @repo/3p-core @repo/3p-posthogLazy loading, privacy controls, retry logic included. Skip to Quick Start →
Why Integrations?
Each analytics provider has different APIs. PostHog needs one setup, Segment another, Vercel a third. Events sent to multiple providers requires duplicated code. Privacy controls (GDPR, CCPA) reimplemented per provider. No retry logic when providers fail. Bundle size bloats from loading everything upfront.
Integrations solves this with a unified adapter pattern, lazy loading, composable utilities, and tree-shaking optimization.
Production-ready with PostHog, Segment, and Vercel support, retry logic, circuit breakers, privacy controls, and batching.
Use cases
- Multi-provider analytics — Send events to PostHog, Segment, Vercel with single call
- Tree-shaking — Import only what you need, minimal bundle impact (< 5KB)
- Privacy compliance — GDPR/CCPA with IP anonymization, DNT respect
- Resilient tracking — Retry logic, circuit breakers, failover handling
- Lazy loading — Load providers only when needed, faster page loads
How it works
Integrations provides adapters and orchestration:
import { LazyMultiProvider } from "@repo/3p-core/orchestration/lazy-multi-provider";
const analytics = new LazyMultiProvider({
providers: {
posthog: {
enabled: true,
priority: 1,
loader: async () => {
const { PostHogAdapter } = await import("@repo/3p-posthog/adapter");
return new PostHogAdapter({
provider: "posthog",
apiKey: process.env.POSTHOG_KEY!
});
}
}
}
});
// Single call reaches all providers
await analytics.track({ name: "Purchase", properties: { value: 100 } });Uses BaseAdapter pattern for consistency, lazy loading for performance, and composable utilities (retry, privacy, batching) for resilience.
Key features
Tree-shaking — Import only adapters you use, minimal bundle impact
Lazy loading — Providers loaded on-demand, not at page load
Multi-provider — PostHog, Segment, Vercel with single API
Privacy controls — GDPR/CCPA compliance with IP anonymization
Retry logic — Exponential backoff, circuit breakers, failover
Batching — Queue events, flush on interval or size threshold
Quick Start
1. Install packages
# Core + PostHog
pnpm add @repo/3p-core @repo/3p-posthog
# Add Segment or Vercel as needed
pnpm add @repo/3p-segment @repo/3p-vercel2. Create multi-provider analytics
import { LazyMultiProvider } from "@repo/3p-core/orchestration/lazy-multi-provider";
export const analytics = new LazyMultiProvider({
providers: {
posthog: {
enabled: !!process.env.POSTHOG_KEY,
priority: 1,
loader: async () => {
const { PostHogAdapter } = await import("@repo/3p-posthog/adapter");
return new PostHogAdapter({
provider: "posthog",
apiKey: process.env.POSTHOG_KEY!
});
}
}
}
});3. Track events across providers
"use client";
import { analytics } from "#/lib/analytics";
export function Button() {
async function handleClick() {
await analytics.track({
name: "Button Clicked",
properties: { id: "cta" },
});
}
return <button onClick={handleClick}>Click Me</button>;
}4. Add composable utilities
import { withRetry } from "@repo/3p-core/composable/with-retry";
import { withPrivacy } from "@repo/3p-core/composable/with-privacy";
import { withBatching } from "@repo/3p-core/composable/with-batching";
import { analytics } from "./analytics";
// Chain utilities for retry, privacy, batching
let enhanced = analytics;
enhanced = withRetry(enhanced, { maxRetries: 3 });
enhanced = withPrivacy(enhanced, { gdprCompliant: true });
enhanced = withBatching(enhanced, { batchSize: 100 });
export { enhanced as analytics };That's it! You now have multi-provider analytics with retry logic, privacy controls, and batching.
Production setup with all protections
Combine retry, privacy, and batching for production:
const adapter = new PostHogAdapter({ provider: "posthog", apiKey: key });
const resilient = withRetry(withPrivacy(withBatching(adapter, { batchSize: 100 }), { gdprCompliant: true }), {
maxRetries: 3
});Technical Details
For Developers: Technical implementation details
Available Packages
| Package | Description | Status |
|---|---|---|
| @repo/3p-core | Core utilities, adapters, and orchestration | ✅ Complete |
| @repo/3p-posthog | PostHog analytics & feature flags | ✅ Complete |
| @repo/3p-segment | Segment analytics & warehousing | ✅ Complete |
| @repo/3p-vercel | Vercel Analytics & Web Vitals | ✅ Complete |
Architecture
graph TB
subgraph Core["Core Utilities"]
BaseAdapter["BaseAdapter"]
Utils["Utilities: Retry, Privacy, Batching"]
Composable["Composable: withRetry, withBatching, withPrivacy"]
end
subgraph Providers["Provider Adapters"]
PostHog["PostHog (feature flags, events)"]
Segment["Segment (events, warehouse)"]
Vercel["Vercel (web vitals, analytics)"]
end
subgraph Orchestration["Orchestration"]
MultiProvider["LazyMultiProvider"]
Router["Router"]
end
Core -->|extends| Providers
Providers -->|managed by| Orchestration
MultiProvider -->|uses| Utils
classDef coreStyle fill:#8b5cf6,color:#fff
classDef providerStyle fill:#ec4899,color:#fff
classDef orchestrationStyle fill:#06b6d4,color:#fff
class Core coreStyle
class Providers providerStyle
class Orchestration orchestrationStyleExecution Modes
Broadcast Mode (Default)
// Send to ALL enabled providers
const result = await analytics.track(event);
// result.results = { posthog: true, segment: true, vercel: true }Failover Mode
// Try providers in priority order, stop at first success
const analytics = new LazyMultiProvider({
providers: {
/* ... */
},
execution: { mode: "failover" }
});Parallel Mode
// Send to all providers simultaneously
const analytics = new LazyMultiProvider({
providers: {
/* ... */
},
execution: { mode: "parallel", timeout: 5000 }
});Composable Utilities
Retry with Exponential Backoff
import { withRetry } from "@repo/3p-core/composable/with-retry";
const resilient = withRetry(adapter, {
maxRetries: 3,
backoffMultiplier: 2, // 1s, 2s, 4s
maxRetryDelay: 30000
});
await resilient.track(event);Privacy & GDPR Compliance
import { withPrivacy } from "@repo/3p-core/composable/with-privacy";
const compliant = withPrivacy(adapter, {
anonymizeIp: true,
respectDoNotTrack: true,
gdprCompliant: true,
ccpaCompliant: true,
cookieConsent: true
});
// PII automatically filtered
await compliant.track({ email: "user@example.com", userId: "123" });
// Result: { userId: "123_hashed" } - email removedBatching & Flushing
import { withBatching } from "@repo/3p-core/composable/with-batching";
const batched = withBatching(adapter, {
batchSize: 100,
flushInterval: 5000,
maxQueueSize: 1000
});
// Events batched automatically
await batched.track(event1);
await batched.track(event2);
await batched.track(event3);
// Manual flush
await batched.flush();Chaining Composables
import { withRetry } from "@repo/3p-core/composable/with-retry";
import { withPrivacy } from "@repo/3p-core/composable/with-privacy";
import { withBatching } from "@repo/3p-core/composable/with-batching";
let analytics = adapter;
analytics = withRetry(analytics, { maxRetries: 3 });
analytics = withPrivacy(analytics, { gdprCompliant: true });
analytics = withBatching(analytics, { batchSize: 100 });
// Now has retry, privacy, AND batching
await analytics.track(event);Error Handling
Circuit Breaker Pattern
import { CircuitBreaker } from "@repo/3p-core/utils/retry";
const breaker = new CircuitBreaker(
5, // Failure threshold
60000 // Reset timeout (1 min)
);
try {
const result = await breaker.execute(async () => {
return await adapter.track(event);
});
} catch (error) {
if (error.message === "Circuit breaker is OPEN") {
console.warn("Provider temporarily disabled");
}
}
// Check state
console.log(breaker.getState()); // 'CLOSED' | 'OPEN' | 'HALF_OPEN'Graceful Degradation
try {
await analytics.track(event);
} catch (error) {
// Fallback to console logging
console.log("[Analytics Fallback]", event);
}Security Best Practices
Never Expose Secret Keys Client-Side
// ❌ WRONG: Secret in client bundle
const adapter = new PostHogAdapter({
apiKey: process.env.POSTHOG_SECRET_KEY
});
// ✅ CORRECT: Use public keys only
const adapter = new PostHogAdapter({
apiKey: process.env.NEXT_PUBLIC_POSTHOG_KEY
});Validate User Input
import { validateEvent } from "@repo/3p-core/utils/validation";
const validation = validateEvent(userGeneratedEvent);
if (!validation.valid) {
console.error("Invalid event:", validation.errors);
return;
}
// Use sanitized version
await adapter.track(validation.sanitized);Avoid Tracking Sensitive Data
// ❌ WRONG: Never track PII
await adapter.track({
properties: {
email: user.email,
creditCard: "1234-5678-9012-3456"
}
});
// ✅ CORRECT: Track anonymized identifiers
await adapter.track({
userId: user.id, // Hashed if GDPR enabled
properties: {
amount: 99.99,
product_id: "prod_123"
}
});Testing
Unit Testing Adapters
import { describe, it, expect, vi } from "vitest";
import { PostHogAdapter } from "@repo/3p-posthog/adapter";
describe("PostHogAdapter", () => {
it("tracks events correctly", async () => {
const adapter = new PostHogAdapter({
provider: "posthog",
apiKey: "test-key"
});
const result = await adapter.track({
name: "Test Event",
properties: { test: true }
});
expect(result).toBe(true);
});
});Mock Provider for Testing
class MockAdapter {
async track() {
return true;
}
async identify() {
return true;
}
async page() {
return true;
}
}
// Use in tests instead of real adapters
const adapter = new MockAdapter();Performance Metrics
| Metric | Target | Notes |
|---|---|---|
| Bundle Size | < 5KB | Tree-shaking optimized |
| Init Time | < 50ms | Lazy loading |
| Track Latency | < 10ms | Non-blocking |
| Batch Flush | < 1s | Default 5s interval |
Configuration
Environment Variables
# PostHog
NEXT_PUBLIC_POSTHOG_KEY=phc_xxxxx
POSTHOG_SECRET_KEY=phc_xxxxx
# Segment
NEXT_PUBLIC_SEGMENT_KEY=xxxxx
SEGMENT_SECRET_KEY=xxxxx
# Vercel
VERCEL_ANALYTICS_ID=xxxxxTroubleshooting
Events Not Being Sent
// 1. Check if provider is enabled
console.log(analytics.isProviderEnabled("posthog"));
// 2. Verify API key
console.log(process.env.POSTHOG_KEY);
// 3. Check network requests in DevTools
// Look for requests to posthog.com
// 4. Enable debug logging
import { setLogger } from "@repo/3p-core/utils/logger";
setLogger("debug");High Queue Size
// Monitor batching metrics
const metrics = analytics.getMetrics?.();
console.log("Queue size:", metrics?.queueSize);
console.log("Error count:", metrics?.errorCount);
// Flush manually if needed
await analytics.flush?.();Package Documentation
- @repo/3p-core - Core utilities and orchestration
- @repo/3p-posthog - PostHog integration
- @repo/3p-segment - Segment integration
- @repo/3p-vercel - Vercel Analytics integration
Related Documentation
- @repo/analytics - Main analytics wrapper
- @repo/observability - Error tracking