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

# Klaviyo

> Send automated emails through Klaviyo when customers edit their orders. Connect Shopify Flow, Revize, and Klaviyo to notify customers about any order change.

## What you need

* Shopify Flow (available on all Shopify plans)
* A Klaviyo account with the [Klaviyo Shopify app](https://apps.shopify.com/klaviyo-email-marketing) installed
* Revize installed with Shopify Flow triggers enabled

<Info>
  Prefer to skip the setup? We can configure the entire Shopify Flow + Klaviyo integration for you. [Reach out](/support/contact).
</Info>

## How it works

Revize fires a Shopify Flow trigger whenever a customer edits their order. You connect that trigger to Klaviyo's "Track an Event" action, which sends the order data to Klaviyo. From there, you build a Klaviyo Flow to send the email.

Revize trigger → Shopify Flow → Klaviyo event → Klaviyo email

***

## Available triggers

You can send Klaviyo emails for any of these Revize triggers:

* **Order edited** — fires on any order edit, including product changes and discount code edits
* **Shipping address updated**
* **Email address updated**
* **Phone number updated**
* **Delivery date updated**
* **Order cancelled**
* **Support ticket created**
* **Tax invoice generated**

Each trigger follows the same setup process. Only the trigger you select in Shopify Flow, the event name you send to Klaviyo, and the event properties change.

***

## Part 1: Set up Shopify Flow

### Step 1: Find your Klaviyo Public API Key

<Steps>
  <Step title="Log in to Klaviyo">
    Go to your Klaviyo dashboard.
  </Step>

  <Step title="Open Settings">
    Click your account name in the bottom-left corner, then go to **Settings**.
  </Step>

  <Step title="Navigate to API Keys">
    Go to the **API Keys** section.
  </Step>

  <Step title="Copy your Public API Key">
    Copy the **Public API Key** (a short alphanumeric code). You will need this in Step 3.
  </Step>
</Steps>

<Warning>
  Make sure you copy the **Public** API key, not the Private API key. The public key is the shorter one.
</Warning>

***

### Step 2: Create a Shopify Flow workflow

<Steps>
  <Step title="Open Shopify Flow">
    In your Shopify Admin, go to **Apps → Shopify Flow** and click **Create workflow**.
  </Step>

  <Step title="Select a Revize trigger">
    Click **Select a trigger**, search for **Revize**, and choose the trigger you want (e.g., Order edited, Shipping address updated, etc.).
  </Step>

  <Step title="Add a Wait action">
    Click the **+** below the trigger and add a **Wait** action. Set the duration to **10 seconds**.
  </Step>

  <Step title="Add a Get Order Data action">
    Click the **+** below the Wait step and add a **Get Order Data** action (Shopify action).

    Configure it as follows:

    * Set **Select a query** to **Advanced**
    * In the **Edit query** field, enter: `id:{{order.legacyResourceId}}`
    * Set **Maximum number of orders** to **1**
    * Set **Sort data by** to **Updated at, Descending**
  </Step>
</Steps>

<Note>
  **Why the 10-second wait?** It gives Shopify's API time to reflect the latest order changes before fetching fresh data. The Get Order Data step then pulls the correct current line items and variants.
</Note>

### Step 3: Add the Klaviyo "Track an Event" action

<Steps>
  <Step title="Search for Klaviyo">
    In the actions list, search for **Klaviyo** and select **Track an Event**.
  </Step>

  <Step title="Fill in the fields">
    Use the table below to fill in each field.
  </Step>
</Steps>

| Field                      | Value                           |
| -------------------------- | ------------------------------- |
| **Klaviyo Public API Key** | Your Public API Key from Step 1 |
| **Event Name**             | See the event name table below  |
| **Customer Email Address** | `{{order.customer.email}}`      |
| **Customer First Name**    | `{{order.customer.firstName}}`  |
| **Customer Last Name**     | `{{order.customer.lastName}}`   |

#### Event names by trigger

Use a descriptive event name so you can identify each trigger in Klaviyo:

| Revize Trigger           | Recommended Event Name         |
| ------------------------ | ------------------------------ |
| Order edited             | `Revize_Order_Edited`          |
| Shipping address updated | `Revize_Address_Updated`       |
| Email address updated    | `Revize_Email_Updated`         |
| Phone number updated     | `Revize_Phone_Updated`         |
| Delivery date updated    | `Revize_Delivery_Date_Updated` |
| Order cancelled          | `Revize_Order_Cancelled`       |
| Support ticket created   | `Revize_Support_Ticket`        |
| Tax invoice generated    | `Revize_Tax_Invoice`           |

<Tip>
  You can name these events anything you like. These are just our recommended names to keep things organized.
</Tip>

### Step 4: Set Customer Properties

In the **Customer Properties** field, paste the following JSON:

```json theme={null}
{
  "$email": "{{order.customer.email}}",
  "$first_name": "{{order.customer.firstName}}",
  "$last_name": "{{order.customer.lastName}}"
}
```

This tells Klaviyo which customer profile to associate the event with.

### Step 5: Set Event Properties

In the **Event Properties** field, paste the JSON that matches your trigger. This uses freshly fetched order data from the Get Order Data step, so Klaviyo always gets the correct current data.

<Tabs>
  <Tab title="Order Edited">
    Use this when you want to send the full updated order details, including line items:

    ```liquid theme={null}
    {% for single_order in getOrderData %}
    {
      "order_id": "{{single_order.id}}",
      "order_name": "{{single_order.name}}",
      "order_number": "{{single_order.legacyResourceId}}",
      "total_price": "{{single_order.totalPriceSet.shopMoney.amount}}",
      "subtotal_price": "{{single_order.subtotalPriceSet.shopMoney.amount}}",
      "total_tax": "{{single_order.totalTaxSet.shopMoney.amount}}",
      "total_shipping": "{{single_order.totalShippingPriceSet.shopMoney.amount}}",
      "currency": "{{single_order.currencyCode}}",
      "edited_at": "{{single_order.updatedAt}}",
      "customer_email": "{{single_order.customer.email}}",
      "customer_name": "{{single_order.customer.firstName}} {{single_order.customer.lastName}}",
      "line_items": [{% assign comma = "" %}{% for item in single_order.lineItems %}
        {% if item.currentQuantity != 0 %}{{comma}}
        {"title": {{item.title | json}}, "quantity": {{item.currentQuantity}},
         "price": "{{item.originalUnitPriceSet.shopMoney.amount}}",
         "variant_title": {{item.variantTitle | json}}, "sku": {{item.sku | json}}}
        {% assign comma = "," %}{% endif %}
      {% endfor %}]
    }
    {% endfor %}
    ```

    <Warning>
      Do not wrap the `line_items` array brackets `[ ]` in quotes. The brackets must be outside all quotes for Klaviyo to receive a proper array.
    </Warning>
  </Tab>

  <Tab title="Address / Email / Phone / Delivery Date">
    Use this for shipping address, contact info, or delivery date updates. Sends order summary without line items:

    ```liquid theme={null}
    {% for single_order in getOrderData %}
    {
      "order_id": "{{single_order.id}}",
      "order_name": "{{single_order.name}}",
      "order_number": "{{single_order.legacyResourceId}}",
      "total_price": "{{single_order.totalPriceSet.shopMoney.amount}}",
      "currency": "{{single_order.currencyCode}}",
      "updated_at": "{{single_order.updatedAt}}",
      "customer_email": "{{single_order.customer.email}}",
      "customer_name": "{{single_order.customer.firstName}} {{single_order.customer.lastName}}",
      "shipping_address": "{{single_order.shippingAddress.address1}}, {{single_order.shippingAddress.city}}, {{single_order.shippingAddress.province}} {{single_order.shippingAddress.zip}}, {{single_order.shippingAddress.country}}"
    }
    {% endfor %}
    ```
  </Tab>

  <Tab title="Cancellation">
    Use this for order cancellation events:

    ```liquid theme={null}
    {% for single_order in getOrderData %}
    {
      "order_id": "{{single_order.id}}",
      "order_name": "{{single_order.name}}",
      "order_number": "{{single_order.legacyResourceId}}",
      "total_price": "{{single_order.totalPriceSet.shopMoney.amount}}",
      "currency": "{{single_order.currencyCode}}",
      "cancelled_at": "{{single_order.updatedAt}}",
      "customer_email": "{{single_order.customer.email}}",
      "customer_name": "{{single_order.customer.firstName}} {{single_order.customer.lastName}}"
    }
    {% endfor %}
    ```
  </Tab>
</Tabs>

<Note>
  The `{% for single_order in getOrderData %}` loop reads from the freshly fetched order data, not the original trigger. This ensures correct data every time.
</Note>

### Step 6: Turn on the workflow

<Steps>
  <Step title="Review all fields">
    Make sure everything is filled in correctly.
  </Step>

  <Step title="Turn on the workflow">
    Click **Turn on workflow** in the top-right corner.
  </Step>

  <Step title="Done">
    The workflow is now active. Every time a customer triggers that action through Revize, the event is sent to Klaviyo with up-to-date order data.
  </Step>
</Steps>

***

## Part 2: Set up the Klaviyo email

### Step 7: Create a Klaviyo Flow

<Steps>
  <Step title="Create a new Flow">
    In Klaviyo, go to **Flows → Create Flow** and select **Build your own**.
  </Step>

  <Step title="Set the trigger">
    For the trigger, choose **Metric** and search for the event name you used (e.g., `Revize_Order_Edited`).
  </Step>

  <Step title="Add an email action">
    Drag an **Email** action into the flow.
  </Step>

  <Step title="Design your template">
    Use the variables below to pull in order data dynamically.
  </Step>
</Steps>

### Step 8: Email template variables

Use these variables in your Klaviyo email template:

| Data             | Klaviyo Variable               |
| ---------------- | ------------------------------ |
| Customer Name    | `{{ event.customer_name }}`    |
| Order Number     | `{{ event.order_name }}`       |
| Subtotal         | `{{ event.subtotal_price }}`   |
| Total Tax        | `{{ event.total_tax }}`        |
| Shipping         | `{{ event.total_shipping }}`   |
| Total Price      | `{{ event.total_price }}`      |
| Currency         | `{{ event.currency }}`         |
| Edit Date        | `{{ event.edited_at }}`        |
| Customer Email   | `{{ event.customer_email }}`   |
| Shipping Address | `{{ event.shipping_address }}` |

### Displaying line items

To display each product in the edited order, use this loop in your Klaviyo email template:

```liquid theme={null}
{% for item in event.line_items %}
  {{ item.title }}
  Variant: {{ item.variant_title }}
  Qty: {{ item.quantity }}
  Price: {{ item.price }}
{% endfor %}
```

Wrap this loop in a table or styled HTML in your Klaviyo email template to match your brand.

### Example email

Here is an example of how your email subject and body might look:

```
Subject: Your order {{ event.order_name }} has been updated

Hi {{ event.customer_name }},

Your order has been updated. Here is your revised summary:

{% for item in event.line_items %}
  {{ item.title }} ({{ item.variant_title }})
  Qty: {{ item.quantity }}  |  Price: {{ item.price }} {{ event.currency }}
{% endfor %}

Total: {{ event.currency }} {{ event.total_price }}
```

***

## Prevent duplicate emails

If a customer makes multiple quick edits in one session, Klaviyo may send multiple emails. To prevent this:

1. Open your Klaviyo Flow
2. Add a **Flow Filter**
3. Set it to suppress if the customer received this email in the **last 5 minutes**

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Flow shows 'Succeeded' but no event in Klaviyo" icon="circle-exclamation">
    Double-check that the **Public API Key** in Shopify Flow matches the one in your Klaviyo account. This is the most common issue.
  </Accordion>

  <Accordion title="Event arrives but data is empty" icon="circle-exclamation">
    The Event Properties JSON may be invalid. Make sure there are no line breaks inside string values and that `line_items` uses `[ ]` brackets without surrounding quotes.
  </Accordion>

  <Accordion title="Wrong variant showing in line items" icon="circle-exclamation">
    Make sure you are using the **Get Order Data** step with the 10-second wait, and that your Event Properties use the `getOrderData` loop, not `order.lineItems` directly.
  </Accordion>

  <Accordion title="Multiple emails being sent" icon="circle-exclamation">
    Add a **Flow Filter** in Klaviyo to suppress if the customer received this email in the last 5 minutes.
  </Accordion>

  <Accordion title="Where to find the metric in Klaviyo" icon="circle-question">
    Go to **Analytics → Metrics** and search for your event name (e.g., `Revize_Order_Edited`). It is created automatically the first time an event is received.
  </Accordion>

  <Accordion title="How to verify it worked" icon="circle-check">
    Go to **Audience → Profiles** in Klaviyo, find the customer email, and check their **Activity** tab for the event.
  </Accordion>
</AccordionGroup>

***

## Want multiple triggers?

You can set up separate Shopify Flow workflows for each trigger. For example:

* **Workflow 1:** Order edited → `Revize_Order_Edited` → "Your order has been updated" email
* **Workflow 2:** Address updated → `Revize_Address_Updated` → "Your shipping address has been changed" email
* **Workflow 3:** Order cancelled → `Revize_Order_Cancelled` → "Your order has been cancelled" email

Each workflow follows the same steps above. Just change the trigger, event name, and event properties.
