---
title: "Instrumentation Spec"
description: "Specifies event tracking and analytics instrumentation requirements for a feature. Use when defining what data to collect, ensuring consistent tracking implementation, or documenting analytics requirements for engineering."
generated: true
source: scripts/generate-skill-pages.py
tags:
  - Measure
  - validation
---

:::note[Quick facts]
**Phase:** Measure | **Version:** 2.0.0 | **Category:** validation | **License:** Apache-2.0
:::

**Try it:** `/instrumentation-spec "Your context here"`

An instrumentation spec defines what analytics events to track, when to fire them, and what properties to include. It serves as a contract between product and engineering, ensuring consistent data collection that enables accurate measurement. Good instrumentation specs prevent the "we can't answer that question because we didn't track it" problem.

## When to Use

- Before engineering implements a new feature
- When defining analytics requirements for experiments
- When auditing existing tracking for gaps or inconsistencies
- When onboarding a new analytics tool
- Before launch to ensure measurement is in place

## How to Use

Use the `/instrumentation-spec` slash command:

```
/instrumentation-spec "Your context here"
```

Or reference the skill file directly: `skills/measure-instrumentation-spec/SKILL.md`

## Instructions

When asked to create an instrumentation spec, follow these steps:

1. **Define Analytics Goals**
   Start with the questions you need to answer. What will you measure? What decisions will this data inform? This prevents over-instrumentation while ensuring nothing important is missed.

2. **Identify Events to Track**
   List each user action or system event that should be tracked. Follow consistent naming conventions (typically `noun_verb` or `verb_noun` in snake_case). Each event should represent a distinct, meaningful action.

3. **Specify Event Triggers**
   For each event, describe exactly when it fires. Be precise: "When user clicks Submit button" vs. "When form is submitted successfully." These are different events with different meanings.

4. **Define Event Properties**
   List the properties (attributes) attached to each event. Include property name, data type, description, and example values. Properties provide context that makes events useful.

5. **Document User Properties**
   Identify persistent user-level attributes that should be associated with all events (e.g., subscription tier, account creation date). These enable segmentation in analysis.

6. **Address PII and Privacy**
   Flag any properties that contain personally identifiable information. Document how PII should be handled . hashing, encryption, or exclusion.

7. **Create Testing Checklist**
   Define how QA should verify that tracking is implemented correctly. Include steps to validate events fire at the right times with correct properties.

## Output Template

# Instrumentation Spec: [Feature Name]

## Overview

**Feature:** [Feature being instrumented]

**Analytics Goals:**
<!-- What questions will this data help answer? -->

1. [Question 1]
2. [Question 2]
3. [Question 3]

**Analytics Platform:** [e.g., Amplitude, Mixpanel, Segment, custom]

**Naming Convention:** [e.g., snake_case: feature_action]

## Event Inventory

### [Event Name]

| Field | Value |
|-------|-------|
| **Event Name** | `[event_name]` |
| **Trigger** | [Exact condition when event fires] |
| **Description** | [What this event represents] |

**Properties:**

| Property | Type | Required | Description | Example |
|----------|------|----------|-------------|---------|
| [property_1] | string | Yes | [Description] | [Example value] |
| [property_2] | number | No | [Description] | [Example value] |
| [property_3] | boolean | Yes | [Description] | [Example value] |

---

### [Event Name]

| Field | Value |
|-------|-------|
| **Event Name** | `[event_name]` |
| **Trigger** | [Exact condition when event fires] |
| **Description** | [What this event represents] |

**Properties:**

| Property | Type | Required | Description | Example |
|----------|------|----------|-------------|---------|
| [property_1] | string | Yes | [Description] | [Example value] |
| [property_2] | number | No | [Description] | [Example value] |

---

## User Properties

<!-- Persistent properties associated with the user, included with all events -->

| Property | Type | Description | Set When | Example |
|----------|------|-------------|----------|---------|
| [user_property_1] | string | [Description] | [When this is set/updated] | [Example] |
| [user_property_2] | string | [Description] | [When this is set/updated] | [Example] |

## PII & Privacy Considerations

<!-- Flag and document handling of sensitive data -->

### PII Properties

| Property | PII Type | Handling |
|----------|----------|----------|
| [property] | [email/phone/name/etc.] | [Hash before sending / Do not send / Encrypt] |

### Consent Requirements

- [Consent requirement 1]
- [Consent requirement 2]

### Data Retention

- [Retention policy for this data]

## Implementation Notes

<!-- Technical details for engineering -->

### SDK/Integration

- **Platform:** [Web, iOS, Android, Backend]
- **SDK:** [SDK name and version]
- **Initialization:** [Any special setup required]

### Event Timing

- [Note about when events should be sent relative to user actions]
- [Batching or real-time requirements]

## Testing Checklist

<!-- How QA verifies correct implementation -->

### Event Validation

- [ ] **[event_name]:** Navigate to [location], perform [action], verify event fires with properties: [list key properties to check]
- [ ] **[event_name]:** Navigate to [location], perform [action], verify event fires with properties: [list key properties to check]

### Property Validation

- [ ] Verify [property] is [string/number/boolean] type
- [ ] Verify [property] is present when [condition]
- [ ] Verify [property] value is within expected range [range]

### Edge Cases

- [ ] Verify events fire correctly on [slow network]
- [ ] Verify events fire correctly after [session timeout]
- [ ] Verify events do not fire when [condition that should prevent firing]

### Debug Tools

- [How to access event stream in debug mode]
- [How to validate in analytics dashboard]

## Example Output

<details>
<summary>Instrumentation Spec: User Onboarding</summary>

# Instrumentation Spec: User Onboarding

## Overview

**Feature:** New user onboarding flow (5 steps: Welcome, Profile, Team, Integrations, Complete)

**Analytics Goals:**

1. What is the overall onboarding completion rate?
2. Where do users drop off in the onboarding flow?
3. How long does each step take, and what's the total onboarding time?
4. Which integrations are users connecting during onboarding?
5. Does skipping optional steps correlate with lower activation?

**Analytics Platform:** Amplitude

**Naming Convention:** snake_case, format: `onboarding_[action]`

## Event Inventory

### onboarding_started

| Field | Value |
|-------|-------|
| **Event Name** | `onboarding_started` |
| **Trigger** | When user lands on onboarding welcome screen for the first time |
| **Description** | Marks the beginning of a user's onboarding journey |

**Properties:**

| Property | Type | Required | Description | Example |
|----------|------|----------|-------------|---------|
| source | string | Yes | How user arrived (signup, invite, sso) | "signup" |
| referrer | string | No | Marketing attribution source | "google_ads_q1" |
| device_type | string | Yes | User's device category | "mobile_web" |
| signup_date | string | Yes | ISO date of account creation | "2026-01-14" |

---

### onboarding_step_viewed

| Field | Value |
|-------|-------|
| **Event Name** | `onboarding_step_viewed` |
| **Trigger** | When user navigates to any onboarding step |
| **Description** | Tracks visibility of each onboarding step |

**Properties:**

| Property | Type | Required | Description | Example |
|----------|------|----------|-------------|---------|
| step_number | number | Yes | Sequential step number (1-5) | 2 |
| step_name | string | Yes | Human-readable step name | "profile_setup" |
| is_return_visit | boolean | Yes | Whether user previously visited this step | false |
| time_since_start | number | No | Seconds since onboarding_started | 45 |

---

### onboarding_step_completed

| Field | Value |
|-------|-------|
| **Event Name** | `onboarding_step_completed` |
| **Trigger** | When user successfully completes a step (clicks Continue/Next) |
| **Description** | Tracks completion of individual onboarding steps |

**Properties:**

| Property | Type | Required | Description | Example |
|----------|------|----------|-------------|---------|
| step_number | number | Yes | Sequential step number (1-5) | 2 |
| step_name | string | Yes | Human-readable step name | "profile_setup" |
| time_on_step | number | Yes | Seconds spent on this step | 32 |
| was_skipped | boolean | Yes | If user clicked Skip instead of completing | false |
| completion_method | string | Yes | How step was completed (manual, skip, auto) | "manual" |

---

### onboarding_step_skipped

| Field | Value |
|-------|-------|
| **Event Name** | `onboarding_step_skipped` |
| **Trigger** | When user clicks Skip on a skippable step |
| **Description** | Tracks when users choose to skip optional steps |

**Properties:**

| Property | Type | Required | Description | Example |
|----------|------|----------|-------------|---------|
| step_number | number | Yes | Sequential step number | 4 |
| step_name | string | Yes | Human-readable step name | "integrations" |
| time_on_step | number | Yes | Seconds spent before skipping | 8 |

---

### onboarding_integration_connected

| Field | Value |
|-------|-------|
| **Event Name** | `onboarding_integration_connected` |
| **Trigger** | When user successfully connects an integration during Step 4 |
| **Description** | Tracks which integrations users connect during onboarding |

**Properties:**

| Property | Type | Required | Description | Example |
|----------|------|----------|-------------|---------|
| integration_name | string | Yes | Name of the integration | "slack" |
| integration_category | string | Yes | Category of integration | "communication" |
| connection_time | number | Yes | Seconds to complete OAuth flow | 12 |
| is_first_integration | boolean | Yes | Whether this is user's first connected integration | true |

---

### onboarding_completed

| Field | Value |
|-------|-------|
| **Event Name** | `onboarding_completed` |
| **Trigger** | When user completes the final step and exits onboarding |
| **Description** | Marks successful completion of the onboarding flow |

**Properties:**

| Property | Type | Required | Description | Example |
|----------|------|----------|-------------|---------|
| total_time | number | Yes | Total seconds from started to completed | 180 |
| steps_completed | number | Yes | Number of steps completed (not skipped) | 4 |
| steps_skipped | number | Yes | Number of steps skipped | 1 |
| integrations_count | number | Yes | Number of integrations connected | 2 |
| completion_path | string | Yes | Ordered list of step outcomes | "done,done,done,skip,done" |

---

### onboarding_abandoned

| Field | Value |
|-------|-------|
| **Event Name** | `onboarding_abandoned` |
| **Trigger** | When user navigates away from onboarding without completing (30 min session timeout) |
| **Description** | Tracks when users leave onboarding incomplete |

**Properties:**

| Property | Type | Required | Description | Example |
|----------|------|----------|-------------|---------|
| last_step_viewed | number | Yes | Last step number user saw | 3 |
| last_step_name | string | Yes | Name of last step viewed | "team_invite" |
| time_in_onboarding | number | Yes | Total seconds in onboarding before abandoning | 95 |
| steps_completed | number | Yes | Steps completed before abandoning | 2 |

---

## User Properties

| Property | Type | Description | Set When | Example |
|----------|------|-------------|----------|---------|
| onboarding_status | string | Current onboarding state | Updated on each step completion | "completed" |
| onboarding_completed_date | string | ISO date of completion | Set on onboarding_completed | "2026-01-14" |
| signup_source | string | Attribution for user signup | Set on onboarding_started | "organic" |
| connected_integrations | array | List of connected integrations | Updated on each connection | ["slack", "jira"] |
| account_type | string | Plan type at signup | Set on account creation | "trial" |

## PII & Privacy Considerations

### PII Properties

| Property | PII Type | Handling |
|----------|----------|----------|
| email | Email address | Hash (SHA-256) before sending to analytics |
| team_member_emails | Email addresses | Do not send to analytics; count only |
| full_name | Name | Do not send to analytics |

### Consent Requirements

- Analytics events only sent if user has accepted analytics cookies (GDPR)
- `onboarding_started` includes consent check; if denied, no events fire
- Users can opt out via Settings > Privacy, which sets `analytics_opt_out` user property

### Data Retention

- Event data retained for 24 months
- User properties retained for account lifetime
- PII hashes cannot be reversed; original values stored only in primary database

## Implementation Notes

### SDK/Integration

- **Platform:** Web (React)
- **SDK:** Amplitude JavaScript SDK v8.21.0
- **Initialization:** Initialize on app load, identify user after authentication

### Event Timing

- Events should fire immediately on trigger, not batched
- If offline, queue events and send on reconnection
- Time properties (time_on_step) calculated client-side using performance.now()

### Code Reference

```javascript
// Example event call
amplitude.track('onboarding_step_completed', {
  step_number: 2,
  step_name: 'profile_setup',
  time_on_step: calculateTimeOnStep(),
  was_skipped: false,
  completion_method: 'manual'
});
```

## Testing Checklist

### Event Validation

- [ ] **onboarding_started:** Create new account, verify event fires on welcome screen with correct source
- [ ] **onboarding_step_viewed:** Navigate through each step, verify event fires for each with correct step_number
- [ ] **onboarding_step_completed:** Complete profile step, verify event fires with time_on_step > 0
- [ ] **onboarding_step_skipped:** Skip integrations step, verify event fires with step_name = "integrations"
- [ ] **onboarding_integration_connected:** Connect Slack, verify event fires with integration_name = "slack"
- [ ] **onboarding_completed:** Complete full flow, verify event fires with accurate total_time
- [ ] **onboarding_abandoned:** Start onboarding, close browser, verify event fires after 30 min timeout

### Property Validation

- [ ] Verify step_number is integer 1-5, never 0 or > 5
- [ ] Verify time_on_step is positive number, never negative
- [ ] Verify completion_path format matches "done|skip" comma-separated pattern
- [ ] Verify is_return_visit correctly detects revisiting completed steps

### Edge Cases

- [ ] Verify events fire correctly after page refresh mid-onboarding
- [ ] Verify events fire correctly after session timeout and re-login
- [ ] Verify events do not duplicate if user navigates back and forward
- [ ] Verify onboarding_abandoned does not fire if user completes

### Debug Tools

- Access Amplitude debug panel: append `?amplitude_debug=true` to URL
- View events in browser console: `amplitude.getInstance().logLevel = 'DEBUG'`
- Validate in Amplitude: User Lookup > search by user_id > Event Stream

</details>

## Real-World Examples

See this skill applied to three different product contexts:

<details>
<summary>Storevine (B2B): Storevine B2B ecommerce platform . Campaigns send flow and first-campaign flow analytics instrumentation</summary>

**Prompt:**

```
/instrumentation-spec

Feature: Campaigns . campaign send flow + guided first-campaign flow
Analytics platform: Amplitude

Events I need to instrument:
1. campaign_created . merchant saves a campaign draft
2. campaign_sent . merchant sends a campaign
3. first_send_completed . merchant sends their FIRST campaign ever
   (milestone event for the non-adopter hypothesis)
4. attribution_recorded . a purchase is linked to a campaign click
   within the 7-day attribution window

Prior work:
- Experiment design: A/B test using first_send_completed as primary metric
- Spike summary: SendGrid webhook attribution confirmed; unique_args
  includes campaign_id, merchant_id, recipient_customer_id

PII note: Subscriber email addresses must NOT be sent to Amplitude.
Only customer_id (pseudonymous internal identifier).

Need: full instrumentation spec with event definitions, properties,
PII handling, implementation notes, and QA testing checklist.
```

---

**Output:**

# Instrumentation Spec: Campaigns Send Flow and First-Campaign Flow

</details>

<details>
<summary>Brainshelf (Consumer): Brainshelf consumer PKM app . Resurface feature analytics instrumentation spec</summary>

**Prompt:**

```
/instrumentation-spec

resurface analytics events for amplitude. need the full spec before
sprint 8 starts so alex and jess can instrument during the build.

events:
1. resurface_opt_in . user enables the digest
2. resurface_digest_sent . server sends a digest email
3. resurface_digest_opened . user opens the email (caveat: apple MPP)
4. resurface_item_clicked . user clicks an item in the digest
5. resurface_unsubscribe . user unsubscribes
6. resurface_cadence_changed . user changes frequency
7. resurface_digest_skipped . server skips sending (no qualifying items,
   exclusion window exhausted, etc.)

also need user properties: digest_enabled, digest_cadence, digest_timezone.

keep it tight. chloe wants to review before sprint planning on monday.
```

---

**Output:**

# Instrumentation Spec: Resurface Digest

</details>

<details>
<summary>Workbench (Enterprise): "Workbench enterprise collaboration platform: Blueprints v1 GA instrumentation spec"</summary>

**Prompt:**

```
/instrumentation-spec

I need the instrumentation spec for Blueprints v1 GA. Here are the events I've identified from the PRD and experiment results:

**Core lifecycle events:**
1. `blueprint_created` -- when an author creates a new Blueprint from a template
2. `section_completed` -- when a required section transitions from empty to non-empty
3. `section_cleared` -- when a required section transitions from non-empty to empty
4. `approval_requested` -- when an author submits a Blueprint for approval
5. `approval_granted` -- when an approver approves a Blueprint
6. `approval_rejected` -- when an approver rejects a Blueprint
7. `blueprint_published` -- when an approved Blueprint is published to the team workspace

**Key properties I need on each event:**
- Standard: account_id, user_id, blueprint_id, template_id, timestamp
- blueprint_created: creation_method (wizard/canvas), template_name, required_section_count, optional_section_count
- section_completed/cleared: section_id, section_name, is_required, word_count
- approval events: approval_chain_type (sequential/parallel), approver_position, approval_cycle_number
- blueprint_published: time_to_approved_hours, total_approval_cycles, co_editor_count

**PII concerns:**
- user_id is internal (UUID), not PII
- We must NOT capture section content in events -- only metadata
- Account names should not appear in event properties; use account_id only

**SDK:** Workbench Analytics SDK (server-side collector, JavaScript client)

Please generate the full instrumentation spec with testing checklist.
```

**Output:**

# Instrumentation Spec: Workbench Blueprints v1

</details>

## Quality Checklist

Before finalizing, verify:

- [ ] Event names follow consistent naming convention
- [ ] Each event has a clear, unambiguous trigger
- [ ] Properties include data types and example values
- [ ] PII is identified and handling is documented
- [ ] Events map to the analytics questions you need to answer
- [ ] Testing checklist enables QA verification

## Output Format

Use the template in `references/TEMPLATE.md` to structure the output.
