> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sequenzy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sync Rules

> Automatically manage tags based on events

# Sync Rules

Sync rules automatically add and remove tags when events occur. They're the glue between events and tags, enabling powerful automation without manual intervention.

## How Sync Rules Work

When an event is triggered for a subscriber:

```
Event: "saas.purchase"
         │
         ▼
┌─────────────────────────┐
│    Check Sync Rules     │
│    for this event       │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────┐
│   Add Tags: "customer"  │
│   Remove: "lead",       │
│           "trial"       │
└─────────────────────────┘
```

Sync rules are managed in Settings, or programmatically: the
[API](/api-reference/sync-rules/get) exposes `GET`/`PUT /api/v1/sync-rules`,
the CLI has `sequenzy sync-rules get` and `sequenzy sync-rules update`, and
the MCP server provides `get_sync_rules` / `update_sync_rules` tools.

## Optional Platform Preset

New workspaces start with no sync rules, so importing or subscribing a contact
does not silently assign a business-stage tag. You can add rules in Settings or
opt into Sequenzy's legacy platform preset for common SaaS and ecommerce events.

The preset includes rules such as:

| Event                  | Tags Added  | Tags Removed                               |
| ---------------------- | ----------- | ------------------------------------------ |
| `saas.purchase`        | `customer`  | `lead`, `past-due`, `cancelled`, `churned` |
| `saas.churn`           | `churned`   | `customer`, `cancelled`, `past-due`        |
| `saas.cancelled`       | `cancelled` | `customer`                                 |
| `saas.payment_failed`  | `past-due`  | —                                          |
| `saas.refund`          | `refunded`  | —                                          |
| `saas.trial_started`   | `trial`     | `lead`                                     |
| `saas.trial_ended`     | —           | `trial`                                    |
| `saas.trial_cancelled` | `cancelled` | —                                          |
| `saas.upgrade`         | —           | —                                          |
| `saas.downgrade`       | —           | —                                          |

<Note>
  The platform preset is not enabled automatically for new workspaces. Review
  its SaaS/ecommerce semantics before enabling it for a services, consulting, or
  other relationship-led business.
</Note>

Legacy workspaces that still inherit platform defaults continue receiving future
updates to that preset for compatibility. Once you save a customized rule set,
it replaces the preset entirely. "Reset to Defaults" in Settings opts back into
the inheriting preset, and saving an empty rule set disables sync rules completely.

Sync rules also run for events Sequenzy records natively - engagement events (`email.opened`, `email.clicked`, `email.replied`), delivery events (`email.bounced`, `email.unsubscribed`, `contact.unsubscribed`), and integration events like `ecommerce.back_in_stock_requested`. Rules on bounce and unsubscribe events only change tags; they never start a sequence for a suppressed contact.

## Sync Rule Anatomy

Each sync rule defines:

```json theme={null}
{
  "event": "saas.purchase",
  "addTags": ["customer"],
  "removeTags": ["lead", "past-due", "cancelled", "churned"]
}
```

| Field        | Description                            |
| ------------ | -------------------------------------- |
| `event`      | The event name that triggers this rule |
| `addTags`    | Tags to add when the event fires       |
| `removeTags` | Tags to remove when the event fires    |

Rules can also carry optional conditions: required subscriber tags, excluded
subscriber tags, and (for commerce events) a product match.

## Product Match Conditions

Commerce events that carry products - order placed, product viewed, added to
cart, and similar - can be filtered by the product itself. Add a **Product
match** condition and the rule only runs when at least one product on the
event matches your selected product tags, collections, or product types.

This is how you build ownership audiences from purchases. For example, a
record store tags every vinyl product with `Vinyl` in Shopify, then adds a
rule:

```json theme={null}
{
  "event": "ecommerce.order_placed",
  "addTags": ["vinyl-collector"],
  "conditions": {
    "purchasedProduct": { "tags": ["Vinyl"] }
  }
}
```

Anyone who buys a vinyl record or accessory is tagged `vinyl-collector`
automatically, ready to receive campaigns for that interest. Within a product
match, values in the same selector are OR'd (any of these tags) and different
selectors are AND'd (must match the tag AND the collection).

<Note>
  Rules with a product match never run for events without product context, so
  they are safe to combine with tag conditions.
</Note>

## Execution Order

When an event triggers:

1. **Event recorded** - Stored in analytics
2. **Remove tags** - Listed tags are removed first
3. **Add tags** - Listed tags are added
4. **Automations checked** - Sequences triggered by new tags

This order ensures clean state transitions.

## Use Cases

### Customer Lifecycle

Track where subscribers are in their journey:

```
Event: saas.trial_started
  Add: "trial"
  Remove: "lead"

Event: saas.purchase
  Add: "customer"
  Remove: "lead", "trial", "past-due"

Event: saas.cancelled
  Add: "cancelled"
  Remove: "customer"

Event: saas.trial_cancelled
  Add: "cancelled"

Event: saas.churn
  Add: "churned"
  Remove: "customer", "cancelled"
```

**Result:** Subscribers always have exactly one lifecycle tag.

### Payment Status

Track payment health:

```
Event: saas.payment_failed
  Add: "past-due"

Event: saas.purchase
  Remove: "past-due"
```

### Subscription Tiers

When integrated with payment providers:

```
Event: subscription.upgraded_to_pro
  Add: "pro-plan"
  Remove: "starter-plan", "free-tier"

Event: subscription.downgraded_to_starter
  Add: "starter-plan"
  Remove: "pro-plan", "enterprise-plan"
```

## Custom Sync Rules

Create custom rules in Settings → Sync Rules:

### Example: Lead Scoring

```
Event: page_viewed_pricing
  Add: "high-intent"

Event: demo_requested
  Add: "demo-lead", "high-intent"
  Remove: "cold-lead"

Event: demo_completed
  Add: "demo-completed"
  Remove: "demo-lead"
```

### Example: Engagement Tracking

```
Event: email.opened
  Add: "engaged"
  Remove: "inactive"

Event: product_used
  Add: "active", "engaged"
  Remove: "inactive", "at-risk"
```

### Example: Onboarding Progress

```
Event: onboarding_step_1_completed
  Add: "onboarding-started"
  Remove: "new-signup"

Event: onboarding_completed
  Add: "onboarded"
  Remove: "onboarding-started"
```

## Sync Rules + Sequences

Sync rules work seamlessly with sequences:

```
1. Event: "saas.purchase"
         │
         ▼
2. Sync Rule Applied
   Add: "customer"
         │
         ▼
3. Sequence Trigger
   "When tag 'customer' added"
         │
         ▼
4. Sequence Starts
   Customer onboarding flow
```

This pattern lets you:

* Keep event handling simple (just fire events)
* Centralize tag logic (sync rules)
* Build flexible sequences (tag-based triggers)

## Payment Provider Integration

When you connect Stripe or other payment providers:

### Automatic Event Firing

The integration automatically fires events:

| Stripe Event                                | Sequenzy Event        |
| ------------------------------------------- | --------------------- |
| `customer.subscription.created`             | `saas.purchase`       |
| `customer.subscription.deleted`             | `saas.cancelled`      |
| `invoice.payment_failed`                    | `saas.payment_failed` |
| `customer.subscription.updated` (downgrade) | `saas.downgrade`      |
| `customer.subscription.updated` (upgrade)   | `saas.upgrade`        |

### Automatic Customer Sync

Stripe customers are synced as subscribers with:

* Email from Stripe customer
* Name from Stripe customer
* Custom attributes for subscription data

## Best Practices

### 1. Design Mutually Exclusive Tags

For lifecycle states, ensure only one tag at a time:

```
✓ Sync rules that remove old state when adding new
  Event: saas.purchase
    Add: "customer"
    Remove: "lead", "trial", "churned"

✗ Tags that can accumulate
  Event: saas.purchase
    Add: "customer"
    (lead and trial remain)
```

### 2. Use System Tags Consistently

Stick to the built-in tag names:

```
✓ "customer", "lead", "trial", "churned"
✗ "is-customer", "isLead", "in_trial"
```

### 3. Test Your Rules

Before going live:

1. Create a test subscriber
2. Trigger events via API
3. Verify tags are added/removed correctly
4. Check that sequences trigger

### 4. Document Custom Rules

Keep a reference of your custom sync rules:

| Event                     | Add             | Remove          | Purpose            |
| ------------------------- | --------------- | --------------- | ------------------ |
| `feature_activated`       | `power-user`    | `new-user`      | Track activation   |
| `support_ticket_opened`   | `needs-support` | —               | Flag for attention |
| `support_ticket_resolved` | —               | `needs-support` | Clear flag         |

### 5. Don't Overcomplicate

Start with default rules, add custom ones as needed:

```
✓ Start simple
  - Use default SaaS events
  - Add custom rules for specific needs

✗ Over-engineer
  - Custom rule for every possible event
  - Complex tag dependencies
```

## Debugging Sync Rules

### Check Event Fired

View subscriber's event history in dashboard.

### Check Tags Applied

View subscriber's current tags after event.

### Common Issues

| Issue                   | Cause                     | Solution                 |
| ----------------------- | ------------------------- | ------------------------ |
| Tag not added           | Event name mismatch       | Check event name exactly |
| Old tag not removed     | Not in `removeTags`       | Add to removeTags array  |
| Sequence not triggering | Tag trigger doesn't match | Verify sequence trigger  |

## Related

<CardGroup cols={2}>
  <Card title="Events" icon="bolt" href="/concepts/events">
    Events that trigger sync rules
  </Card>

  <Card title="Tags" icon="tags" href="/concepts/tags">
    Tags managed by sync rules
  </Card>

  <Card title="Sequences" icon="diagram-project" href="/concepts/sequences">
    Automations triggered by tags
  </Card>

  <Card title="Subscribers" icon="users" href="/concepts/subscribers">
    Contacts that receive tags
  </Card>
</CardGroup>
