> ## 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](/workflows) 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](/events/properties)
* A [Stripe integration](/integrations/stripe) 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](/api-reference/send-event):

<CodeGroup>
  ```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,
    },
  });
  ```
</CodeGroup>

See [Events](/events) and [Event properties](/events/properties) for the full API.

Note: this `approachingPlanLimit` event is specific to your app's usage tracking. The [Stripe integration](/integrations/stripe) 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

<Steps>
  <Step title="Trigger on Event received">
    In the [Workflow builder](/workflows), pick **Event received** and select
    `approachingPlanLimit`.
  </Step>

  <Step title="Filter on plan">
    Add an [audience filter](/workflows#audience-filters) to your workflow so you only send to
    free-plan users: `planName = Free`. Set the filter scope to **All following nodes**.
  </Step>

  <Step title="Personalize the email">
    Use [event properties](/events/properties) 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.
    ```
  </Step>

  <Step title="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.
  </Step>
</Steps>

## 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.
</Tip>

## 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

<CardGroup>
  <Card title="Events" icon="bolt" href="/events" />

  <Card title="Event properties" icon="key" href="/events/properties" />

  <Card title="Stripe integration" icon="credit-card" href="/integrations/stripe" />

  <Card title="Branching workflows" icon="code-branch" href="/workflows/branching" />
</CardGroup>
