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

# Recipe: Upgrade upsell workflow

> Trigger an upsell sequence when a free-plan user hits a usage threshold that a paid plan would solve.

Generic "upgrade now" emails get ignored. Specific ones ("you sent 950 of your 1000 monthly emails") convert. This recipe fires an upsell [Workflow](https://loops.so/docs/workflows.md) only when a user hits a usage threshold that a paid plan would remove, personalized to what they actually did.

## What you need

* An event from your app when the user approaches a plan limit
* A way to pass the usage context as [event properties](https://loops.so/docs/events/properties.md)
* A [Stripe integration](https://loops.so/docs/integrations/stripe.md) is handy but not required

## Send the signal from your app

When a free-plan user hits 80% of any plan limit, fire an event via the [Send event endpoint](https://loops.so/docs/api-reference/send-event.md):

```js REST theme={"dark"}
await fetch("https://app.loops.so/api/v1/events/send", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${process.env.LOOPS_API_KEY}`,
  },
  body: JSON.stringify({
    email: user.email,
    eventName: "approachingPlanLimit",
    planName: "Free",
    eventProperties: {
      usageCurrent: 950,
      usageMax: 1000,
      usagePercent: 95,
    },
  }),
});
```

```ts SDK theme={"dark"}
await loops.sendEvent({
  email: user.email,
  eventName: "approachingPlanLimit",
  contactProperties: {
    planName: "Free",
  },
  eventProperties: {
    usageCurrent: 950,
    usageMax: 1000,
    usagePercent: 95,
  },
});
```

See [Events](https://loops.so/docs/events.md) and [Event properties](https://loops.so/docs/events/properties.md) for the full API.

Note: this `approachingPlanLimit` event is specific to your app's usage tracking. The [Stripe integration](https://loops.so/docs/integrations/stripe.md) covers subscription, invoice, checkout, quote, and dispute events (see the full list in the integration doc), but usage-limit events still need to come from your own backend.

## Build the workflow

**1. Trigger on Event received**

In the [Workflow builder](https://loops.so/docs/workflows.md), pick **Event received** and select
`approachingPlanLimit`.

**2. Filter on plan**

Add an [audience filter](https://loops.so/docs/workflows.md#audience-filters) to your workflow so you only send to
free-plan users: `planName = Free`. Set the filter scope to **All following nodes**.

**3. Personalize the email**

Use [event properties](https://loops.so/docs/events/properties.md) directly in the email. In the
editor, click the `{}` icon above the editor or type `{` and then the event property name:

```
You have sent {usageCurrent} of {usageMax}
emails this month ({usagePercent}%). Upgrade to keep going.
```

**4. Send a follow-up email**

Add a follow-up email to your workflow that is sent 3 days after the initial email.
Your initial "All following nodes" audience filter will still be applied to the follow-up email.

## Why event-triggered beats scheduled

Scheduled "here is our pro plan" campaigns hit people who aren't close to a limit and who did nothing to prompt the message. Event triggers mean every send goes to a user with a concrete reason to upgrade right now.

> [!TIP]
>
> If your pricing has multiple limits (users, storage, emails, integrations),
> fire a separate event type per limit, triggering a separate workflow for each.

## Measuring success

* Open rate: should be higher than a generic upsell because the subject can cite the specific resource
* Upgrade conversion: track via your existing billing system, not in Loops
* Unsubscribe rate: watch this closely, over-sending upsells is a fast way to lose users

## Read more

> [card] [Events](https://loops.so/docs/events.md)

> [card] [Event properties](https://loops.so/docs/events/properties.md)

> [card] [Stripe integration](https://loops.so/docs/integrations/stripe.md)

> [card] [Branching workflows](https://loops.so/docs/workflows/branching.md)


## Related topics

- [Recipe: Onboarding completion workflow](https://loops.so/docs/guides/onboarding-completion.md)
- [Branching workflows](https://loops.so/docs/workflows/branching.md)
- [Recipe: Churn risk segment and re-engagement workflow](https://loops.so/docs/guides/churn-risk-segment.md)
- [Recipe: SaaS customer lifecycle emails](https://loops.so/docs/guides/lifecycle-emails.md)
- [Recipe: Scheduled digest email](https://loops.so/docs/guides/scheduled-digest-email.md)
