Event schemas
Skill almasumdev/awesome-mobile-observability-agent-skills/.github/skills/analytics/event-schemas
Define versioned, validated analytics-event schemas with type-safe wrappers so clients and warehouses agree on shape. Use when formalizing or migrating an existing tracking plan.From its SKILL.md
npx -y skills add almasumdev/awesome-mobile-observability-agent-skills --skill event-schemasAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.9 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it
Versioned Event Schemas
Instructions
Events evolve. Without a schema and versioning, every analytics downstream becomes a minefield of optional fields and silent breaking changes. Treat events like API contracts: schemas, validation, typed wrappers, semver.
1. Schema Format
Use JSON Schema (draft 2020-12) or Protobuf. JSON Schema is more readable for data teams; Protobuf is more robust if your pipeline already speaks it. Example JSON Schema entry:
# analytics-registry.yaml -> compiled to per-event JSON Schema
events:
checkout_started:
version: 2
owner: growth
pii: false
description: "User started the checkout flow."
properties:
cart_value_cents:
type: integer
minimum: 0
currency:
type: string
enum: [USD, EUR, GBP, JPY]
item_count:
type: integer
minimum: 1
source:
type: string
enum: [cart, deeplink, push, widget]
shipping_method:
type: string
enum: [standard, express, pickup]
required: [cart_value_cents, currency, item_count, source]
additionalProperties: false
2. Versioning Rules
- Additive changes (new optional property, new enum value not strictly required): bump patch.
- Required additions or property type changes: bump major; emit under a new event name or with a
schema_versionproperty. Keep the old version valid for at least one release cycle. - Every event carries
schema_versionso the warehouse can route to the correct view.
Never silently drop a property; mark it deprecated: true in the schema and keep accepting it at ingest for one cycle before removal.
3. Validation Pipeline
Three validation boundaries:
- Compile-time (client): typed wrappers generated from the registry (see
product-analytics). Typos or missing required fields fail the build. - Runtime (client): a lightweight validator in debug builds asserts the event matches the schema; in release it logs a meta-event
analytics_invalid_eventand drops the event. - Ingest (server): full JSON Schema validation at the collector; invalid events go to a dead-letter topic and fire a ticket-level alert.
fun track(event: AnalyticsEvent) {
if (BuildConfig.DEBUG) require(SchemaValidator.validate(event.name, event.properties)) {
"Invalid analytics event: ${event.name}"
}
sink.enqueue(event)
}
4. Code Generation
Generate wrappers per platform from the single analytics-registry.yaml:
- Kotlin: KSP or a small Gradle task emits sealed classes into
generated/analytics. - Swift: a
Sources/AnalyticsGenerated/folder produced via a SwiftPM plugin. - Dart: a
build_runnergenerator producinglib/analytics/generated/events.dart. - TypeScript:
json-schema-to-typescriptorquicktypeemitssrc/analytics/generated.ts.
Generated code is checked in so reviews can see diffs, and is regenerated in CI so drift fails the build.
5. Enum Governance
- Enum values are registry-owned. Adding a new value requires a registry PR with an owner and a description.
- A forbidden enum value (e.g.
source="unknown"when unexpected) must come from a sharedUnknownEnumpolicy: either log and drop, or coerce to a sentinelotherand open a ticket. - Warehouse dashboards filter known enum values only; unknown values go to a monitoring query.
6. Nested Data
- Avoid nested objects in analytics events -- most warehouses want flat columns.
- When you must nest (e.g.
items[]), keep it shallow and document the cardinality cap (maxItems: 10). Emit a summary event first (checkout_startedwithitem_count) and a per-item event (cart_item_added) if granularity is needed. - Never put arrays of PII (e.g.
phone_numbers: []).
7. Schema Registry and CI
# .github/workflows/analytics.yml
jobs:
validate-analytics:
steps:
- run: bun run generate:analytics
- run: git diff --exit-code # generated code must match registry
- run: bun run validate:registry # JSON Schema compiles, owners present, no PII flagged false
- run: bun run lint:callsites # grep for untyped track() calls
8. Type-Safe Wrappers (Reminder)
From product-analytics, reject any emission that doesn't go through the typed wrapper. Add a custom lint rule:
- Kotlin:
@RequiresAnalyticsWrapper+ Detekt rule that bans directmixpanel.track("..."). - Swift: SwiftLint custom rule forbidding
Analytics.shared.track(. - Dart: custom analyzer plugin.
- TS: ESLint rule banning
segment.track.
9. Deprecation Workflow
- Mark event/property deprecated in registry with
deprecated_in: "2026.04". - Generated wrappers emit
@Deprecated/@deprecated/// ignore: deprecated_member_use. - Warehouse queries migrate to the replacement.
- After one release cycle, remove the deprecated property from the registry; the wrappers drop it; the ingest schema stops accepting it.
10. Disaster Drills
- Quarterly: purposely break the registry (remove a required field) and verify the typed wrappers fail the build and the ingest validator drops events into the dead-letter topic.
- Verify the dead-letter topic has an alert and a runbook.
Checklist
- Single
analytics-registry.yamldrives schemas and code generation. - Every event has
version,owner,pii,description, and required fields listed. - Typed wrappers are generated per platform and checked in.
- Runtime validation runs in debug; ingest validation at the collector has a dead-letter pipe.
- Enum values are registry-owned; a policy handles unknown values.
- CI fails on registry drift and untyped call sites.
- Deprecation workflow is documented and exercised.
- Quarterly drill verifies end-to-end enforcement.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.