@growth-labs/analytics
v0.2.6
Published
WAE-primary analytics with auto-injected behavioral tracking, attribution, and conversion event routing. Requires **Cloudflare Workers Paid plan** ($5/mo) for WAE access. No D1 fallback for behavioral events.
Downloads
1,434
Readme
@growth-labs/analytics
WAE-primary analytics with auto-injected behavioral tracking, attribution, and conversion event routing. Requires Cloudflare Workers Paid plan ($5/mo) for WAE access. No D1 fallback for behavioral events.
Config
import analytics from '@growth-labs/analytics'
analytics({
siteId: 'fedweek', // Cookie prefix + WAE index
waeBinding: 'ANALYTICS', // WAE binding in wrangler.toml
d1Binding: 'SITE_DB', // D1 for conversion events
cookiePrefix: 'fedweek', // → fedweek_vid, fedweek_sid, fedweek_attr
session: { timeoutMinutes: 30, engagedThresholdSeconds: 10 },
scroll: { thresholds: [25, 50, 75, 90] },
media: { thresholds: [25, 50, 75, 100] },
ecommerce: { enabled: true, currencyCode: 'USD' },
webVitals: { enabled: true },
})What It Injects
Middleware (server-side, every request):
- Reads/creates visitor ID cookie (
{cookiePrefix}_vid) - Manages session cookie (
{cookiePrefix}_sid) - Parses UTM params + referrer → attribution cookie (
{cookiePrefix}_attr) - Writes
page_viewto WAE (anonymous if no consent) - Bot filtering (rejects known bot user-agents)
Routes:
POST /api/analytics/event— beacon receiver for client-side eventsPOST /api/analytics/progress— content progress (reading/watching)
Client script (auto-injected):
- Scroll depth tracking (fires at 25/50/75/90%)
- Media progress tracking (audio + video elements)
- Core Web Vitals (LCP, INP, CLS)
- Outbound link clicks, file downloads, 404 detection
- Form tracking (start, submit, abandon)
- E-commerce events (product_viewed, add_to_cart, checkout_success)
- Search events (search query + result count)
window.glAnalytics.track(eventName, data)public API
Event Routing
| Event type | Destination | Examples | |------------|-------------|---------| | Behavioral | WAE only | page_view, scroll_50, page_exit, time_on_page | | Conversion | WAE + D1 | newsletter_subscribed, checkout_success, form_submit | | System | WAE only | session_start, session_engaged | | Vital | WAE only | web_vital_lcp, web_vital_inp, web_vital_cls |
WAE Schema
20 blobs + 12 doubles per data point. Key fields:
- blob1: eventName, blob2: siteId, blob3: visitorId, blob5: pageUrl
- blob8-10: UTM params, blob11: derivedSource, blob12: country
- blob13: deviceType, blob16: contentSlug, blob18: eventCategory
- double1: timestamp, double2: eventValue
All WAE writes go through writeDataPoint() utility — never construct data points directly.
D1 Tables (prefixed gl_)
gl_conversion_events— conversion event log with e-commerce fieldsgl_analytics_visitors— visitor summary (session count, first/last seen)gl_content_progress— reading/watching progress per visitor per content
Wrangler Bindings
[analytics_engine_datasets]
binding = "ANALYTICS"
[[d1_databases]]
binding = "SITE_DB"
database_id = "..."Runtime Behavior
Server entrypoints side-effect import virtual:growth-labs/analytics/config, so package state seeds itself in the Worker that actually handles the request.
Bindings resolve from the standard Cloudflare surfaces:
cloudflare:workersfor env bindingsAstro.locals.cfContext.waitUntil()for background writes
Legacy locals.runtime is still accepted as a fallback, but consumers should not patch @growth-labs/analytics/state or add package-specific runtime-state middleware.
Consent Integration
Optional peer dependency on @growth-labs/consent. If installed:
- No consent → anonymous page_view only (no visitor ID cookie, no attribution)
- With consent → full tracking (cookies, attribution, all events)
If consent package NOT installed → tracking runs unconditionally.
Client-Side Event API
// gl:* CustomEvent pattern for loose coupling
document.dispatchEvent(new CustomEvent('gl:track', {
detail: { event: 'product_viewed', data: { productId: '123' } }
}))
// Or direct API
window.glAnalytics.track('custom_event', { label: 'something' })Key Patterns
- Virtual module:
virtual:growth-labs/analytics/config - Runtime config self-seeds in middleware and routes via the virtual module
gl:*CustomEvent pattern ondocumentfor loose coupling between client-side packages. Package-localgl:*events are not automatically forwarded; usewindow.glAnalytics.track(...)when an event should be written to WAE.writeDataPoint()is the ONLY way to write to WAE- Bot filtering runs before any tracking
gl_prefix on all D1 table names
