Integrate Glyph customer event tracking into this codebase.
SDK selection:
- Server-side JavaScript/TypeScript: npm install @glyphhq/node
- Client-side web code: npm install @glyphhq/browser
- Python: pip install glyphhq
Prefer server-side instrumentation for business-critical events (payments,
subscription changes); use the browser SDK only for in-product actions and
page views that exist client-side.
Client setup:
- Create ONE shared client per side (e.g. lib/glyph.ts on the server).
- Read the write key from an environment variable (GLYPH_WRITE_KEY on the
server; use the framework's public-env prefix for the browser key). Add
entries to .env.example. Create separate named server and browser keys so
the public browser credential can be rotated independently. Never commit a
real key.
- Use glyph_test_ keys in development, preview, test, and staging. Use
glyph_pk_ keys in production. Keep using the SDK's default ingestion host
unless Glyph explicitly tells you to configure another one.
- Wire the onError callback to the project's existing logger. Never log a
write key, message body, customer-authored content, or sensitive traits.
- Missing keys should make tracking a safe no-op in unconfigured local and
test environments. Tracking failures must not break the customer's action.
Identity rules:
- Call glyph.profile(userId, { email, ...traits }) wherever signup and login
complete, and wherever traits like plan change. email is REQUIRED on every
profile. Traits merge server-side, so partial updates are fine.
- userId must be the app's stable user ID from the database — never an email.
- Do NOT instrument anonymous or pre-signup visitors. Glyph only accepts
known customers; there is no anonymous ID to send.
- Only attribute an event when there is an honest, known customer. Do not
invent an actor for a system or background outcome.
Event selection:
- Do not optimize for a fixed event count. Audit the real product workflows
and select as many meaningful events as needed to explain a customer's
activation, adoption, value received, friction, retention, and lifecycle.
- Prefer semantically dense events over raw clickstream noise. Track completed
workflows, meaningful results, results consumed, explicit feedback, and
bounded failures. Do not track hovers, indiscriminate button clicks,
automatic polling, passive refreshes, or framework lifecycle noise.
- Cover four categories:
1. Activation: account creation, onboarding, and the first moment a customer
reaches value. If the product has workspace, organization, project, or
team creation, decide whether that is a separate activation milestone.
2. Core value: the actions the product is paid for, plus evidence the
customer consumed the result — for example opening it, viewing supporting
detail, sharing it, or completing the next step.
3. Friction: validation failures, rejected operations, processing fallbacks,
errors shown to customers, delivery failures, usage limits, downgrades,
and cancellation attempts. Do not skip these; they often explain behavior
better than successes.
4. Lifecycle: trial started, subscribed, upgraded, downgraded, cancellation
requested, and cancelled — instrument these in authoritative billing
webhooks when those states exist.
- Preserve explicit feedback choices as bounded properties. For example, one
"Feedback submitted" event can distinguish useful, not_relevant, and
dismissed without fragmenting the taxonomy.
- Do not add infrastructure events by reflex. "Invoice paid" is useful only
when payment success answers a customer or revenue question not already
represented by the subscription lifecycle.
Event naming and properties:
- Names are sentence-case, past-tense phrases a human reads on a timeline:
"Report exported", "Export failed". No snake_case, no dot.namespaced.codes.
- Properties are small, flat, and bounded. Include context that helps explain
the moment: object IDs, counts, durations, booleans, result types, surfaces,
and enumerated reasons. Customer attributes belong in profile traits, not
event properties.
- Never put passwords, tokens, full write keys, card numbers, email bodies,
survey answers, notes, support text, search text, arbitrary error messages,
stack traces, or other sensitive/customer-authored content in a trait or
property. Send IDs, counts, lengths, and bounded classifications instead.
Delivery rules:
- In serverless functions and API routes: await glyph.flush() before
returning the response, every time. Check early-return and error paths too.
- Explicit flush() calls are the delivery guarantee in short-lived runtimes.
Do not change the SDK's periodic flush interval as a substitute for calling
flush(). Leave the interval at its default unless the runtime has a clear
reason to change it and every short-lived boundary has been audited.
- In scripts and workers: call close() before exit.
- Python has no background flush thread — flush()/close() explicitly, or
use the client as a context manager.
- The browser queue is in memory and hidden-tab delivery is best effort. Never
rely on browser delivery alone for payments, subscriptions, or other
business-critical events.
- Deduplicate one-time milestones when concurrent requests could emit them
twice. Deduplicate page views and error-boundary events across client
remounts, and debounce filters or search without sending query text.
Process:
- Before installing packages or writing code, inspect auth hooks, server
actions, API routes, jobs, billing webhooks, errors, plan-limit branches,
and authenticated client workflows.
- Present the proposed event list as a table with: event name, category, the
customer question it answers, where it fires, server or browser authority,
safe properties, and any deduplication rule. Include events deliberately
excluded as noise or unsafe. Wait for my confirmation.
- Ask me for the write key setup — I'll create a glyph_test_ key so we can
verify in Glyph's isolated test environment before going live. Create
separate named server and browser keys if both SDKs are used.
- Test non-trivial selection and delivery rules, including deduplication,
safe property mapping, and tracking failure isolation.
- When done: list every file changed, every event added by category, and every
event deliberately omitted. Report the validation commands and explain how
to verify profiles, representative events, failures, and one-time milestones
in the test environment.