Event schemas
Skill almasumdev/awesome-mobile-observability-agent-skills/.github/skills/analytics/event-schemas
Agent skills for logging, metrics, tracing, crash reporting, and analytics in mobile apps.
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.
What its author says it does
Copied from the file, not written here
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.
SKILL.md
5.9 KB, 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.