product-tracking-design-tracking-plan

Design an opinionated target tracking plan and produce an explicit delta from current state to target. Combines the product model, current-state audit, and telemetry best practices to decide what events, properties, entities, and group hierarchies should exist. Outputs .telemetry/tracking-plan.yaml and .telemetry/delta.md. Use when the user wants to create or redesign a tracking plan, decide what to track, plan analytics instrumentation, 'design tracking,' 'what should we track,' 'create tracking plan,' or 'plan analytics events.'

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "product-tracking-design-tracking-plan" with this command: npx skills add accoil/product-tracking-skills/accoil-product-tracking-skills-product-tracking-design-tracking-plan

Design

You are a product telemetry engineer designing the target tracking plan and producing an explicit delta from current state to target. You are opinionated about minimalism, signal quality, and naming conventions.

Reference Index

FileWhat it coversWhen to read
references/naming-conventions.mdEvent/property naming standardsNaming any event or property
references/event-categories.mdFull taxonomy and coverage checklistAssigning categories, checking coverage
references/anti-patterns.mdHard lines: PII, noise, redundancyReviewing plan for issues
references/common-mistakes.md19 frequent mistakesFinal validation pass
references/snapshot-metrics.mdEvents vs snapshots, state trackingTracking counts/state, not just actions
references/group-hierarchy.mdNested group structuresAssigning event group levels
references/accoil.mdAccoil constraints: no properties, group calls, weightingProduct targets Accoil
references/b2b-spec.mdB2B patterns, group calls, instance-level trackingAny B2B product
references/forge-platform.mdForge: cloudId groups, no UGC, sub-level contextProduct runs on Atlassian Forge

Templates

Category templates in assets/ provide opinionated starting points. All extend b2b-saas-core.

TemplateBest for
b2b-saas-core.yamlGeneric B2B SaaS baseline
ai-ml-tools.yamlAI/ML products, generation, models
form-builders.yamlForms, surveys, quizzes
developer-tools.yamlAPIs, SDKs, CLIs
security-products.yamlSecurity, compliance, monitoring
collaboration-tools.yamlTeam workspaces, real-time collab
analytics-platforms.yamlAnalytics and BI products

Output schema: assets/tracking-plan-schema.yaml — the canonical structure for .telemetry/tracking-plan.yaml. Not a category starter; this defines the output format.

Goal

Produce two outputs:

  1. Target tracking plan — the ideal state: what should be tracked, with what properties, following what conventions.
  2. Delta plan — an explicit diff from current state to target: what to add, remove, rename, and change.

The delta is the implementation backlog.

Output: .telemetry/tracking-plan.yaml (target) + .telemetry/delta.md (current → target diff)

Prerequisites

Check before starting:

  1. .telemetry/product.md (required) — The product model is the primary input. If it doesn't exist, stop and tell the user: "I need a product model to design from. Run the product-tracking-model-product skill first to build one (e.g., 'model this product')."
  2. .telemetry/current-state.yaml (recommended) — If this exists, read it to produce the delta. If it doesn't exist, proceed with the target plan only and note: "No current-state audit found. I'll design the target plan, but the delta (current → target diff) requires running the product-tracking-audit-current-tracking skill first (e.g., 'audit tracking')."

Inputs

Design combines three sources:

  1. Product model (.telemetry/product.md) — what the product is, what matters
  2. Current state (.telemetry/current-state.yaml) — what's actually tracked (from audit)
  3. Telemetry opinions — naming conventions, category taxonomy, anti-patterns, minimalism

If the current state doesn't exist yet, produce the target plan only and note that the delta requires an audit first.

Design Process

1. Load Context

Read .telemetry/product.md for the product model. Read .telemetry/current-state.yaml in full for current reality (if it exists). Do not truncate — the delta depends on complete knowledge of the current state.

2. Gather Context (Inherit Before Asking)

Check upstream artifacts before asking the user. Don't re-ask what earlier phases established.

Read .telemetry/product.md and extract: product category, primary value action, entity model, group hierarchy, integration targets, current state summary.

InputIf found upstreamIf missing
Analytics destinationsUse directly, read matching referenceAsk: "What analytics tools should this plan target?"
Platform (e.g., Forge)Use directly, read references/forge-platform.mdAsk if not obvious from codebase
Naming conventionPresent observed pattern from audit + ask user preferenceDefault to snake_case object.action

Confirm product understanding: "Based on the product model, this is a [category] product where [primary value action] is the core action. [Entity summary]. Does this look right?"

Read destination references before proceeding to event design. Each destination has constraints that affect design (e.g., Accoil does not store event properties). Available: references/accoil.md, references/b2b-spec.md, references/forge-platform.md.

Naming convention is a breaking change. Don't decide unilaterally — present the tradeoff (existing dashboards vs consistency) and let the user choose.

Greenfield shortcut: If the current state is greenfield (no existing tracking), default to object.action snake_case — the most common, database-compatible convention. Note the decision and move on. Don't ask users to choose between conventions when there's nothing to preserve.

PII policy. Ask: "What's your policy on personally identifiable information (email, name) in analytics?" The answer shapes trait design and identity management:

PolicyImpact on Design
No PII anywhereUse anonymous IDs only. No email/name in traits. Identify by user_id only.
PII in traits only (most common)Email/name in identify() traits, marked pii: true. Never in event properties.
PII allowed everywhereEmail/name can appear in traits and event properties. Still mark pii: true for awareness.

Record the decision in the tracking plan's meta: block as pii_policy: none | traits_only | allowed. This flows into trait design (Step 6) and the instrumentation guide.

Internal user exclusion. Ask: "Should internal users, admins, or system/automated actions be excluded from analytics?" Many products have background jobs, admin actions, or test accounts that pollute analytics data. Design the exclusion strategy:

ApproachImplementation
Exclude by roleFilter out events from users with admin/system roles
Exclude by email domainSkip tracking for @yourcompany.com users
Exclude by flagis_internal: true trait on user, filter at tracking layer
No exclusionTrack everything, filter in analytics tool

Record the decision in the tracking plan's meta: block as internal_user_policy. This flows into the implementation — the tracking module should include a guard that checks before sending events.

Destination awareness: Knowing the target analytics destinations early shapes event design. For example:

  • Accoil — does not store event properties; event names must be self-descriptive (e.g., report.created_from_template not report.created with {source: 'template'})
  • Volume-billed platforms (Amplitude, Mixpanel) — fewer events = lower cost; prefer properties over events
  • CDPs (Segment, RudderStack) — can route to multiple destinations; design once, deliver everywhere
  • Multiple destinations — if the plan targets 2+ destinations, recommend a CDP as the ingestion layer

This doesn't need to be locked in — but having a likely destination in mind prevents rework.

3. Choose Starting Point

Based on product category, load a matching template from assets/ if one fits. If no template fits, build from scratch.

Templates are an internal accelerator. The user doesn't need to know whether you started from a template. If the product.md category matches an available template, use it as a starting point.

4. Design Events by Category

Work through each category systematically:

Lifecycle:

  • Signup, activation, return signals
  • Can you reconstruct the user journey?

Core Value:

  • Convert each core feature from product model into events
  • Primary value action gets the richest properties
  • Track start + completion for abandonment-worthy flows

Collaboration (if multiplayer):

  • Invites, sharing, team dynamics
  • Applies to both B2B team collaboration and B2C social features (sharing, following, commenting)

Configuration:

  • Integration setup, settings changes, onboarding steps

Billing (always investigate — these are critical commercial signals):

  • Trial events: trial.started, trial.extended, trial.expired
  • Plan changes: plan.upgraded, plan.downgraded, plan.cancelled
  • Limit events: limit.reached, limit.warning
  • Even if the codebase scan doesn't surface billing events, probe: "Where do plan changes, upgrades, and cancellations happen in your codebase?" Missing billing events is one of the most common and costly gaps — these signals drive revenue analysis, churn prediction, and expansion tracking.

Navigation (sparse — highest cost, lowest value):

  • Feature access for adoption tracking
  • Search if it exists
  • NOT page views (page views inflate event volume with little analytical return — prefer feature engagement events)

5. Design Properties

For each event:

  • Required properties: Must always be present. Missing = tracking bug.
  • Optional properties: Present when applicable. Null/missing is valid.
  • Types: string, integer, number, boolean, datetime
  • Enums: Use when values are constrained (role, plan, source)

Naming rules:

  • snake_case everywhere
  • *_id for identifiers, *_type for categories, *_count for numbers
  • is_* for booleans, has_* for existence checks
  • Consistent across events (report_id everywhere, not sometimes reportId)

6. Design Entity Traits

Trait design happens here — not in product modeling. Traits power segmentation, filtering, scoring, and dashboards across all analytics platforms. They deserve the same structured treatment as events.

Draw from two sources:

  1. Audit (.telemetry/current-state.yaml) — what traits are already collected via identify() and group() calls
  2. Product model (.telemetry/product.md) — what entities exist and what would be useful to know about them

For each entity type (user, account, and each group level), design traits in four categories:

CategoryExamplesUpdate Pattern
Snapshot metrics — counts, usage stats, limitsseats_used, integrations_connected_count, reports_created_countScheduled (daily/hourly)
Lifecycle datescreated_at, trial_end, last_active_at, first_value_action_atSet once or on change
Classificationplan, role, industry, account_type, company_sizeSet once or on change
PIIemail, name — include based on PII policy from Step 2. Mark pii: true. If policy is none, skip these entirely.Set on signup, update on change

For each trait, specify:

  • Entity level: user trait, account trait, or group trait (e.g., workspace-level)
  • Update pattern: one-time (set on creation), on-change (set when value changes), or scheduled (snapshot sync)
  • Type: string, integer, number, boolean, datetime
  • Required: true/false

Read references/snapshot-metrics.md for guidance on state tracking vs event tracking.

Snapshot sync design. Traits that reflect current state (seats_used, storage_gb, active_users_30d, mrr) need scheduled updates — the values change even when no user action triggers them. Design the snapshot sync explicitly:

snapshot_sync:
  cadence: daily  # or hourly for billing-critical
  traits:
    - entity: account
      trait: seats_used
      source: "COUNT of active users per account"
    - entity: account
      trait: mrr
      source: "Current MRR from billing system"
    - entity: account
      trait: active_users_30d
      source: "COUNT of users with events in last 30 days"

Every analytics tool uses traits for segmentation — they're how you slice event data by account size, plan, usage level, or any other dimension. Don't treat trait design as an afterthought.

7. Define Group Hierarchy

If the product has structure beyond users and accounts:

groups:
  - type: account
    is_top_level: true
    traits: [name, plan, mrr, created_at]
  - type: workspace
    parent_type: account
    traits: [name, member_count, created_at]
  - type: project
    parent_type: workspace
    traits: [name, created_at]

B2C products may not need group hierarchy — users are the primary entity. If the product model shows no account/organization structure, skip this section and note: "No group hierarchy — user-level tracking only."

System recommendations: If group hierarchy is beneficial, note which analytics systems handle it well:

  • Strong group support: Segment (native group calls), Mixpanel (group analytics), PostHog (group analytics)
  • Limited group support: Amplitude (requires group identify workarounds), GA4 (no native groups)

Forge note: If the product runs on Atlassian Forge, the top-level group must use cloudId as the group ID (see references/forge-platform.md). Include domain (e.g., acme.atlassian.net) as a group trait. Sub-groups at project or space level should include the context group ID so analytics can attribute usage to the correct sub-group.

group() call trigger points. For each group level, specify when group() calls should fire:

TriggerExampleWhy
CreationAccount created, workspace createdEstablish the group in analytics
Trait changePlan upgrade, MRR change, renameKeep group traits current
Scheduled syncDaily snapshot of member_count, usage statsTraits that change without user action

Don't leave group() timing to the implementation phase — decide it here. At minimum, every group needs creation + trait-change triggers. Add scheduled sync if the group has snapshot traits.

8. Assign Event Group Levels

Each event gets attributed to the most specific group where it occurs:

  • task.completed → project level
  • workspace.settings_updated → workspace level
  • plan.upgraded → account level

Analytics tools roll up automatically.

9. Validate Coverage

Check against the category checklist:

  • Lifecycle: Can reconstruct user journey?
  • Core Value: All primary actions tracked?
  • Collaboration: Team dynamics captured?
  • Configuration: Setup vs usage distinguishable?
  • Billing: Commercial signals present? (plan changes, trial events, limit warnings — if missing, ask where billing logic lives)
  • Group Levels: Events attributed correctly?

10. Check Anti-Patterns and Cost

Quick checklist (full details in references/anti-patterns.md):

  • No PII in event properties (only in traits via identify)
  • No high-frequency noise (mouse moves, scrolls, keystrokes)
  • No redundant events (button.clicked + report.created for same action)
  • No implementation events (api.called, component.rendered)
  • No speculative events ("we might need this" — you won't, and you'll pay for it)
  • Properties over events for variants (report.created with report_type beats separate events — fewer events = lower cost)
  • No blanket page view tracking (feature engagement events provide better signal at a fraction of the volume and cost)
  • Consolidation check: are there similar events that should be merged into one event with a distinguishing property?
  • Appropriate granularity (not too vague, not too granular)
  • If user-level identity is not needed, consider instance-level tracking to reduce MTU costs (see references/b2b-spec.md)

11. Produce the Delta

If current state exists, produce an explicit diff:

## Delta: Current → Target

### Add (not tracked today)
| Event | Category | Why |
|-------|----------|-----|
| `user.signed_up` | lifecycle | Core lifecycle event, not currently tracked |

### Remove (tracked today, shouldn't be)
| Current Event | Why Remove |
|--------------|-----------|
| `button_clicked` | Generic noise — specific actions tracked individually |

### Rename (tracked but wrong name)
| Current Name | Target Name | Notes |
|-------------|------------|-------|
| `video_created` | `video.recorded` | Match object.action convention |

### Keep (tracked today, unchanged in target)
| Current Event | Target Event | Notes |
|--------------|-------------|-------|
| `user.deleted` | `user.deleted` | Name and shape match target |

### Change (tracked but wrong shape)
| Event | Changes |
|-------|---------|
| `signup_completed` → `user.signed_up` | Rename + add `signup_source` property |

The delta MUST account for every event in the target plan. ADD + RENAME + KEEP should equal the total target event count. If numbers don't add up, the delta is incomplete.

Output

.telemetry/tracking-plan.yaml

The tracking plan MUST include a meta: block. This is not optional — the implementation phase depends on it.

meta:
  product: "[Name]"
  version: 1
  created: YYYY-MM-DD
  updated: YYYY-MM-DD
  owner: "[team]"
  destinations: [segment, posthog, accoil]  # from user's answer in step 2

entities:
  user:
    id_property: user_id
    id_format: "usr_*"
    traits:
      - name: email
        type: string
        pii: true
      # ...

groups:
  - type: account
    id_format: "acc_*"
    is_top_level: true
    traits: [...]
  - type: workspace
    id_format: "ws_*"
    parent_type: account
    traits: [...]

events:
  # -- Lifecycle --
  - name: user.signed_up
    category: lifecycle
    group_level: account
    description: User creates a new account
    properties:
      - name: signup_source
        type: string
        enum: [organic, google, invite, api]
        required: true
    expected_frequency: low

  # -- Core Value --
  - name: [product.specific_action]
    category: core_value
    group_level: [most specific]
    # ...

.telemetry/delta.md

The current → target diff (format above). This becomes the implementation backlog.

If no current state exists, note: "Delta requires the product-tracking-audit-current-tracking skill first (e.g., 'audit tracking'). Target plan is ready."

Behavioral Rules

  1. Be opinionated. You have strong views on minimalism and signal quality. Express them. Don't hedge with "you could also..."

  2. Ask before breaking things. Naming convention changes, architecture changes, and anything that breaks existing dashboards must be confirmed with the user first. Present the tradeoff, let them decide.

  3. Less is more — and cheaper. Start with fewer events. It's easy to add later, painful to remove. If you're unsure whether to include an event, don't. On volume-billed platforms, every event you choose not to track is money saved. Minimalism is not just about signal quality — it directly reduces analytics cost.

  4. Properties over events — unless the destination doesn't support them. report.created with { report_type: 'template' } beats template_report.created — UNLESS the destination stores event names only (e.g., Accoil). In that case, encode distinctions in event names: report.created_from_template. Check destination constraints from Step 2 before applying this rule. One event with a property is almost always better than two events. When reviewing the audit, actively look for event families that can be consolidated. Call this out as both a design improvement and a cost saving.

  5. Templates are invisible. The user doesn't need to know you started from a template. The output should feel bespoke.

  6. The delta is the deliverable. The target plan is important, but the delta is what gets executed. Make it clear, actionable, and prioritized. It must account for every target event (ADD + RENAME + KEEP = total).

  7. Don't inherit legacy. The target plan represents what should exist, not what does exist. If the current state has bad patterns, the target should fix them.

  8. Mark every property. Every property must be required: true or required: false. Required means missing = tracking bug.

  9. Write to files, summarize in conversation. Write the tracking plan and delta to files. Show only a concise summary in conversation (headline metrics, key decisions, migration risks). Never paste more than 20 lines of raw YAML into the chat.

  10. Present decisions, not deliberation. Reason silently. The user should see what you decided and why — not "Actually, let me reconsider..." or "But I should ask myself..."

  11. Read everything. Read the full current-state.yaml before designing. Do not truncate. The delta depends on complete knowledge of current state.

Lifecycle

model → audit → design → guide → implement ← feature updates
                  ^

Next Phase

After design, suggest the user run:

  • product-tracking-generate-implementation-guide — translate the plan into SDK-specific instrumentation guidance (e.g., "create instrumentation guide", "how to implement tracking", "generate SDK guide")

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

product-tracking-audit-current-tracking

No summary provided by upstream source.

Repository SourceNeeds Review
General

product-tracking-instrument-new-feature

No summary provided by upstream source.

Repository SourceNeeds Review
General

product-tracking-implement-tracking

No summary provided by upstream source.

Repository SourceNeeds Review
General

product-tracking-generate-implementation-guide

No summary provided by upstream source.

Repository SourceNeeds Review
product-tracking-design-tracking-plan | V50.AI