Product analytics
Skill almasumdev/awesome-mobile-observability-agent-skills/.github/skills/analytics/product-analytics
Design a mobile product-analytics event taxonomy with consistent naming, governance, and a registry. Use when introducing new events or cleaning up an existing Amplitude / Mixpanel / Segment / Firebase Analytics setup.From its SKILL.md
npx -y skills add almasumdev/awesome-mobile-observability-agent-skills --skill product-analyticsAssembled 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
6.9 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it
Product Analytics Taxonomy
Instructions
Product analytics only pays off if events are consistently named, typed, and owned. Treat the event taxonomy as a schema: reviewed, versioned, and enforced.
1. Event Naming Convention
<object>_<action> in snake_case, past tense.
- Good:
checkout_started,payment_submitted,paywall_viewed,onboarding_step_completed. - Bad:
Click Checkout Button,paymentFlow,clicked_button_42.
Rules:
- Objects come from a fixed domain list (e.g.
checkout,paywall,onboarding,feed,profile). - Actions come from a fixed verb list (
viewed,started,completed,submitted,failed,dismissed,tapped). - No event for "user did something general" -- always tie to an object.
2. Standard Properties
Every event carries a standard envelope:
| Property | Type | Notes |
|---|---|---|
event_id | uuid | generated client-side, for idempotency |
event_time | iso-ts | wall clock; server-side also stamps ingest time |
app_version | string | 4.12.0+4120 |
platform | enum | ios / android / flutter-ios / ... |
os_version | string | major.minor only |
device_class | enum | low / mid / high |
locale | string | en-US |
session_id | string | rotated on sign-out / new cold start |
user_id_hash | string | optional, only after auth |
experiment_buckets | map | { "paywall_v2": "variant_a" } |
consent_state | enum | granted / denied / not_requested |
Analytics SDKs (Amplitude, Mixpanel, Segment, Firebase Analytics) provide hooks to set these as user / super properties.
3. Event-Specific Properties
- Primitives only (string, number, boolean). No nested objects.
- Enums must be documented; a new enum value requires a registry update.
*_idfields must be hashed if they can identify a person; raw ids only for non-PII objects (product id, article id).- Include
source(home,search,deeplink) so funnels can differentiate entry points.
Example:
{
"event": "checkout_started",
"properties": {
"cart_value_cents": 2599,
"currency": "USD",
"item_count": 3,
"source": "cart",
"shipping_method": "standard"
}
}
4. Kotlin Wrapper
object Analytics {
fun track(event: AnalyticsEvent) {
if (Consent.current == Consent.Denied) return
val envelope = StandardEnvelope.current()
mixpanel.track(event.name, JSONObject(envelope + event.properties + redactedEnum(event)))
}
}
sealed class AnalyticsEvent(val name: String, val properties: Map<String, Any?>) {
class CheckoutStarted(cartValueCents: Int, currency: String, itemCount: Int, source: Source)
: AnalyticsEvent("checkout_started", mapOf(
"cart_value_cents" to cartValueCents,
"currency" to currency,
"item_count" to itemCount,
"source" to source.wire
))
}
Sealed classes prevent typos; the registry equals the set of subclasses.
5. Swift Wrapper
enum AnalyticsEvent {
case checkoutStarted(cartValueCents: Int, currency: String, itemCount: Int, source: Source)
var name: String {
switch self {
case .checkoutStarted: return "checkout_started"
}
}
var properties: [String: Any] {
switch self {
case let .checkoutStarted(v, c, n, s):
return ["cart_value_cents": v, "currency": c, "item_count": n, "source": s.rawValue]
}
}
}
6. Dart Wrapper (Flutter)
sealed class AnalyticsEvent {
String get name;
Map<String, Object?> get properties;
}
class CheckoutStarted extends AnalyticsEvent {
CheckoutStarted({required this.cartValueCents, required this.currency,
required this.itemCount, required this.source});
final int cartValueCents;
final String currency;
final int itemCount;
final Source source;
@override String get name => 'checkout_started';
@override Map<String, Object?> get properties => {
'cart_value_cents': cartValueCents,
'currency': currency,
'item_count': itemCount,
'source': source.wire,
};
}
7. TypeScript Wrapper (RN)
export type AnalyticsEvent =
| { name: 'checkout_started'; properties: { cart_value_cents: number; currency: string; item_count: number; source: Source } }
| { name: 'payment_submitted'; properties: { method: PaymentMethod; outcome: Outcome } };
export function track(event: AnalyticsEvent): void {
if (consent.current === 'denied') return;
analytics.track(event.name, { ...standardEnvelope(), ...event.properties });
}
8. Governance
- Single source of truth: a
analytics-registry.yamlin the repo lists every event, every property, allowed enum values, owner team, and PII status. - Pull request gate: CI check fails if a new event lacks a registry entry or a tracking plan link.
- Retirement policy: events deprecated must stay defined in the registry for one release cycle, then be removed from both client and data warehouse views.
- Review: data / product owns the taxonomy; engineering owns the implementation.
9. Anti-Patterns
button_clickedwith abutton_nameproperty. Create separate events; it's five events, not one.- Logging raw API payloads as properties. Always extract the specific fields you need.
- Emitting
user_signed_inmultiple times per session (guard with session state). - Setting user id before consent is granted.
10. Validation
- Unit test each wrapper: event names match the registry, enum values are exhaustive.
- A lint script parses
analytics-registry.yamland the source, failing if a wrapper emits an unregistered property. - Schema validation on ingest (see
event-schemas).
Checklist
- Events follow
<object>_<action>past-tense snake_case. - Standard envelope (version, platform, device class, consent) is attached on every event.
- A typed wrapper per platform enforces naming and property types.
-
analytics-registry.yamlexists and CI fails on drift. - Owners are assigned per event; retirement policy is documented.
- Consent state gates all tracking calls.
- Unit tests enforce registry-code consistency.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.