Every event, reconciled against live Segment traffic.
A catalog of analytics events reconciled across three vectors: what the repos instrument, what actually fires (observed in SEGMENT_EVENTS in Snowflake across 7 production sources), and which of those reach Amplitude. Segment is the source of truth for existence and volume; Amplitude is one destination among several. Names in code are Title Case; Segment stores them UPPER_SNAKE — both are shown. Observed through 2026-08-26.
Reconciliation — three states
The gap between what the code defines and what Segment actually receives is the most important thing this dictionary surfaces. Click a card to filter the table.
✅ Confirmed
Instrumented in code and observed firing in Segment. Volume and last-seen date come straight from the warehouse, so these are events you can trust.
☁️ Undocumented
Firing in Segment but no instrumentation located in the indexed repos — mostly other product surfaces (SolidCareer, LCMS, Admin, VILT) that were never inventoried, plus newer frontend apps.
🚫 Unobserved
Instrumented in code but zero warehouse traffic. Either it never fires, or it's filtered at the Segment source/destination before landing. Verified against TRACKS — no event reaches the warehouse without a table.
The Events Table
Search by name; filter by reconciliation state, source, lifecycle, domain, or emission vector. Click a row for observed payload, volume, code name, and source file.
| Event | Source | Vector | Domain | Reconciliation | Lifecycle | Volume | Last seen |
|---|
Emission Vectors
Six ways platform-backend and platform-frontend emit analytics events — each needs a different search to enumerate, which is why a naive grep undercounts. A seventh row covers events observed in the warehouse that no indexed repo accounts for: the other product surfaces (SolidCareer, LCMS, Admin, VILT, Live Training) have never had their instrumentation inventoried.
| Vector | Where | Event name comes from | Count |
|---|---|---|---|
| SegmentEvent / …Contract | BE app/*/Events/*.php | eventName literal / EVENT_NAME const / interpolated | 126 |
| Track (abstract base) | BE Stripe, subscriptions, PasswordReset… | getName() override or class name | 14 |
| HasSegment trait | BE listeners calling $this->track() | class name → words (default) | 21 |
| OccurredActionTrack | BE Eloquent observers | literal passed to ::dispatch() (Created/Updated/Deleted X) | 69 |
| trackEvent (store / object) | FE mixin + { event: … } object form + helpers | string arg, event: key, or wrapper arg | 49 |
| direct dispatch / Hotjar | FE dispatch('segment/track'), window.hj('event') | string literal | 5 |
| (observed only) | Not located — other product surfaces + newer frontend apps | observed in SEGMENT_EVENTS; no code vector found | 125 |
How Events Flow
Everything converges on Segment, which fans out to the Snowflake warehouse, Amplitude (product analytics), ChurnZero, and Hotjar. The warehouse destination is what this dictionary observes: it writes one table per event name into SEGMENT_EVENTS.<SOURCE>, so it sees every source, not just the two that feed Amplitude. Names are stored UPPER_SNAKE, and some are re-derived downstream from properties (e.g. user_type=Manager → MANAGER_*).
// Backend (source: PLATFORM_BACKEND) Event class / Track / HasSegment / OccurredActionTrack → Segment.track() → Segment → Snowflake · Amplitude · ChurnZero // Frontend (source: PLT_PROD_FRONTEND) trackEvent() | dispatch('segment/track') → Segment → Snowflake · Amplitude window.hj('event', …) → Hotjar (snake_cased, consent-gated) // Other surfaces — warehouse only, never inventoried in code SolidCareer · LCMS · Admin · VILT · Live Training → Segment → Snowflake // The warehouse destination is the observation point for this dictionary Segment → SEGMENT_EVENTS.<SOURCE>.<EVENT_NAME> (one table per event, plus TRACKS)
Base Payload Envelope
Backend events carry a common Segment track envelope; the two base contracts nest the event-specific data differently.
{
"userId": "<uuid>",
"event": "User Viewed A Lesson",
"properties": {
"accountExternalId": …, "contactExternalId": …,
"meta": { "origin":…, "accountUser":{…} },
"data": { /* event-specific */ }
},
"integrations": { "ChurnZero": true }
}{
"userId": "<uuid>",
"event": "Mark Order As Paid",
"properties": { /* eventDetails / getProperties() */ },
"context": { "active": true, "ip": … },
"timestamp": …
}Methodology & Freshness
Built by extracting all six emission vectors from source, then reconciling against the Amplitude taxonomy. Regenerate with .assemble-events.py → .build-event-dictionary.py.
- Backend vectors: grep -rlE "extends SegmentEvent(Contract)?", extends Track, use HasSegment + $this->track(, and OccurredActionTrack::dispatch( literals.
- Frontend vectors: trackEvent('…'), trackEvent({ event: … }), helper wrappers (updateAssignment('…')), dispatch('segment/track'), window.hj('event', …).
- Reconciliation normalizes both sides to UPPER_SNAKE and matches against the Amplitude export.
- To make authoritative: connect Amplitude (or export the Segment tracking plan) for the full taxonomy + properties + volume; and scan the Vue 3 repos (platform, platform-tools, platform-admin, project-puffin) that also feed PLT_PROD_FRONTEND to resolve the platform-only rows.