# Create Tracking Plans using Rudder CLI

This guide shows you how to define and create Tracking Plans in your Data Catalog using Rudder CLI.

## Prerequisites

Before creating a Tracking Plan, ensure you have:

1. [Rudder CLI tool]({{< ref "dev-tools/rudder-cli/" >}}) installed and [authenticated]({{< ref "dev-tools/rudder-cli/data-governance-walkthrough.md#1-authenticate-the-cli-tool" >}})
2. [Events]({{< ref "dev-tools/rudder-cli/data-catalog-and-tracking-plans/data-catalog/events.md" >}}) and [properties]({{< ref "dev-tools/rudder-cli/data-catalog-and-tracking-plans/data-catalog/properties.md" >}}) defined in your [Data Catalog project]({{< ref "dev-tools/rudder-cli/project-setup.md" >}})
3. Optional [custom types]({{< ref "dev-tools/rudder-cli/data-catalog-and-tracking-plans/data-catalog/custom-types.md" >}}) created for validation

## Define Tracking Plans

Using your preferred text editor, create a YAML file in your [Data Catalog project]({{< ref "dev-tools/rudder-cli/project-setup.md" >}}) and add the below content:

### Basic structure

You can define Tracking Plans in YAML files with the `kind: tracking-plan` specification.

```yaml
version: rudder/v1
kind: tracking-plan
metadata:
  name: mytrackingplan
spec:
  id: mytrackingplan
  display_name: "Product Tracking Plan"
  description: "Contains all the events and properties for the Product Tracking Plan."
  rules:
    - type: event_rule
      id: product_viewed_rule
      event: "#event:product_viewed"
      additional_properties: false
      properties:
        - property: "#property:product_sku"
          required: true
```

Each Tracking Plan definition requires:

- A unique identifier (`id`)
- A display name (`display_name`)
- A description (`description`)
- Rules (`rules`) that reference events and their properties

See [Data Catalog YAML Reference]({{< ref "dev-tools/rudder-cli/yaml-data-catalog-and-tracking-plans/_index.md" >}}) for the detailed YAML spec containing Tracking Plan definitions.

### Event rules

Event rules define which events to track and their associated properties. Each rule requires:

- A unique rule identifier (`id`)
- A reference to the event (`event`)
- Property references with validation requirements
- Optional `additional_properties` flag to control unplanned event tracking
- **For non-track events**: `identity_section` parameter to specify where properties should be placed

#### Track events

Track events use the standard `properties` section for their event properties:

```yaml
rules:
  - type: event_rule
    id: product_viewed_rule
    event: "#event:product_viewed"
    additional_properties: false
    properties:
      - property: "#property:product_sku"
        required: true
      - property: "#property:category"
        required: false
      - property: "#property:product_details"  # Object property with nested properties
        required: true
        properties:
          - property: "#property:product_name"
            required: true
          - property: "#property:product_price"
            required: true
```

#### Non-track events (identify, page, screen, group)

For non-track events, you must specify the `identity_section` parameter to define where the properties should be placed in the RudderStack event payload:

{{< tabs tabTotal="3" >}}
{{% tab tabName="Identify events" %}}
```yaml
rules:
  - type: event_rule
    id: user_identify_rule
    event: "#event:user_identify"
    additional_properties: false
    identity_section: "traits"  # Properties go in traits section
    properties:
      - property: "#property:email"
        required: true
      - property: "#property:first_name"
        required: true
      - property: "#property:last_name"
        required: false
```
{{% /tab %}}
{{% tab tabName="Page/Screen events" %}}
```yaml
rules:
  - type: event_rule
    id: homepage_viewed_rule
    event: "#event:homepage_viewed"
    additional_properties: true
    identity_section: "context.traits"  # Properties go in context.traits section
    properties:
      - property: "#property:page_url"
        required: true
      - property: "#property:referrer"
        required: false
      - property: "#property:user_segment"
        required: false
```
{{% /tab %}}
{{% tab tabName="Group events" %}}
```yaml
rules:
  - type: event_rule
    id: org_association_rule
    event: "#event:org_association"
    additional_properties: false
    identity_section: "traits"  # Properties go in traits section
    properties:
      - property: "#property:company_id"
        required: true
      - property: "#property:company_name"
        required: true
      - property: "#property:company_size"
        required: false
```
{{% /tab %}}
{{< /tabs >}}

#### Identity section options

The `identity_section` parameter accepts the following values:

| Value | Description | Use case |
|-------|-------------|----------|
| `properties` | Properties are placed in the main properties section | Track events (default) |
| `traits` | Properties are placed in the traits section | Identify and Group events |
| `context.traits` | Properties are placed in the context.traits section | Page and Screen events |

{{< info >}}
The `identity_section` parameter is required for all non-track events (identify, page, screen, group).

Track events automatically use the `properties` section and do not need this parameter.
{{< /info >}}

### Nested properties

RudderStack supports nesting properties within a property of `array`, `object`, or `array of object` type while defining Tracking Plan rules — this lets you validate hierarchical data structures that mirror your actual data model.

When referencing properties of `array`, `object`, or `array of object` type with nested properties in your Tracking Plans, add the `properties` key underneath the property reference, as shown:

```yaml
version: rudder/v1
kind: tracking-plan
metadata:
  name: ecommTrackingPlan
spec:
  id: ecommPlan
  display_name: "Checkout Tracking Plan"
  description: "Contains all the events and properties for the checkout flow."
  rules:
    - type: event_rule
      id: page_viewed_rule
      event: "#event:page_viewed"
      additional_properties: true
      properties:
        - property: "#property:page"
          required: true
        - property: "#property:categories" # Object type property
          properties: # Nesting level 1
            - property: "#property:category_id"
            - property: "#property:category_object" # Object type property
              properties: # Nesting level 2
                - property: "#property:category_object_1"
                - property: "#property:category_object_2"
                properties: # Nesting level 3
                  - property: "#property:category_object_3"
                  - property: "#property:category_object_4"
```

{{< info >}}
Note that:

- You can use the `properties` key only with properties that have a type of `array`, `object`, or `array of object`. The validation will fail if you add nested properties to other property types like `string` or `integer`.
- You can nest properties up to **3 levels**, as seen in the above snippet.
- As a best practice, avoid circular dependencies when using custom types as nested properties.
{{< /info >}}

### Examples

The following examples show how to define Tracking Plans for different use cases:

{{< tabs tabTotal="3" >}}
{{% tab tabName="Ecommerce" %}}
```yaml
version: rudder/v1
kind: tracking-plan
metadata:
  name: ecommerce_tracking
spec:
  id: ecommerce_tracking
  display_name: "Ecommerce Tracking"
  description: "Tracking Plan for ecommerce events"
  rules:
    - type: event_rule
      id: product_viewed_rule
      event: "#event:product_viewed"
      properties:
        - property: "#property:sku"
          required: true
        - property: "#property:product_details"  # Object property with nested properties
          required: true
          properties:
            - property: "#property:product_name"
              required: true
            - property: "#property:product_price"
              required: true
```
{{% /tab %}}
{{% tab tabName="Authentication" %}}
```yaml
version: rudder/v1
kind: tracking-plan
metadata:
  name: user_auth_tracking
spec:
  id: user_auth_tracking
  display_name: "User Authentication Tracking"
  description: "Tracking Plan for user authentication events"
  rules:
    - type: event_rule
      id: user_registered_rule
      event: "#event:user_registered"
      properties:
        - property: "#property:email"
          required: true
        - property: "#property:signup_method"
          required: true
        - property: "#property:referral_source"
          required: false
```
{{% /tab %}}
{{% tab tabName="User identification" %}}
```yaml
version: rudder/v1
kind: tracking-plan
metadata:
  name: user_identification_tracking
spec:
  id: user_identification_tracking
  display_name: "User Identification Tracking"
  description: "Tracking Plan for user identification and page view events"
  rules:
    - type: event_rule
      id: user_identify_rule
      event: "#event:user_identify"
      additional_properties: false
      identity_section: "traits"
      properties:
        - property: "#property:email"
          required: true
        - property: "#property:first_name"
          required: true
        - property: "#property:last_name"
          required: false
        - property: "#property:company"
          required: false
    - type: event_rule
      id: homepage_viewed_rule
      event: "#event:homepage_viewed"
      additional_properties: true
      identity_section: "context.traits"
      properties:
        - property: "#property:page_url"
          required: true
        - property: "#property:referrer"
          required: false
        - property: "#property:user_segment"
          required: false
```
{{% /tab %}}
{{< /tabs >}}

## Validate and deploy Tracking Plans

Before deploying your Tracking Plans to the workspace, validate them to ensure they follow the correct structure and meet your requirements.

### Validate Tracking Plans

Run the following command to validate your Tracking Plan definitions:

```shell
rudder-cli validate -l ~/tutorial-catalog
```

The command checks your Tracking Plan definitions for:

- Required fields and correct structure
- Valid event and property references
- Unique identifiers across your catalog
- Proper YAML syntax

If validation succeeds, the command returns no output. If it finds any issues, it displays specific error messages to help you fix them.

### Deploy Tracking Plans

After validating your Tracking Plans, deploy them to your RudderStack workspace:

1. Review the changes before deploying:

```shell
rudder-cli apply -l ~/tutorial-catalog --dry-run
```

2. Deploy the validated Tracking Plans:

```shell
rudder-cli apply -l ~/tutorial-catalog
```

The above command:

- Creates new Tracking Plans in your workspace
- Updates existing plans if you've modified them
- Reports the status of each operation
- Requires confirmation before making changes (unless you use `--confirm=false`)

{{< info >}}
See the [End-to-end Walkthrough]({{< ref "dev-tools/rudder-cli/data-governance-walkthrough.md" >}}) for steps on validating and deploying Tracking Plans along with other Data Catalog resources.
{{< /info >}}

## Best practices

Follow these best practices when defining Tracking Plans:

- **Organization**
   - Group related events
   - Use clear rule IDs
   - Maintain consistent naming

- **Properties**
   - Mark critical properties as required
   - Document property purposes
   - Use appropriate validation

- **Validation**
   - Test all rules
   - Verify references
   - Check property constraints

## Next steps

- [Update your Tracking Plan]({{< ref "dev-tools/rudder-cli/data-catalog-and-tracking-plans/tracking-plans/update.md" >}}) with new events, properties, and validation rules
- Set up [GitHub Actions]({{< ref "dev-tools/rudder-cli/github-actions/_index.md" >}}) for automated Tracking Plan management

<br />

