---
title: "Automate Shopify Abandoned-Cart Emails with n8n and AI"
description: "Build a Shopify abandoned-cart email workflow in n8n. AI personalizes every win-back message. No OpenAI key needed — AI credits are included on AgentRoost."
canonical: https://agentroost.app/en/blog/shopify-abandoned-cart-emails-n8n-ai
date: 2026-06-13T12:00:00Z
---

[Canonical URL](https://agentroost.app/en/blog/shopify-abandoned-cart-emails-n8n-ai)

About 70% of online shopping carts are abandoned before checkout. A well-timed email — one that speaks to what the customer actually left behind — recovers a meaningful slice of those lost sales.

Generic "You left something behind!" templates recover some of them. An email that says *"You were this close to getting the Merino Wool Crew-Neck in forest green — here's why it's worth coming back"* converts significantly better.

This guide walks through building exactly that: a running n8n workflow that catches Shopify checkout abandonment events in real time, waits the right amount of time, then asks an LLM to write a personalized, product-specific email — and sends it.

---

## How the workflow fits together

The flow has five stages:

```
Shopify Webhook → Wait → Check if order placed → AI writes email → Send Email
```

Each stage maps to specific n8n nodes. Let's build it step by step.

---

## Step 1 — Receive the abandonment event from Shopify

**Node: Webhook**

Shopify fires a `checkouts/create` or `checkouts/update` event when a customer fills in their email and adds items but doesn't complete the purchase. You'll catch this with a Webhook node.

In your n8n canvas, add a **Webhook** node. Set the method to `POST`, copy the generated URL — it will look like `https://<your-id>.agentroost.app/webhook/shopify-cart` — and paste it into Shopify:

> Shopify Admin → Settings → Notifications → Webhooks → Create webhook
> Event: `Checkout creation` (and optionally `Checkout update`)
> Format: JSON
> URL: your Webhook node URL

The payload arrives with everything you need: `email`, `line_items` (product titles, quantities, prices), `subtotal_price`, and `abandoned_checkout_url` (Shopify's recovery link).

---

## Step 2 — Wait before sending anything

**Node: Wait**

Don't email immediately. Customers who abandon a cart sometimes complete the purchase within 30–60 minutes on a different device or after a phone call. Emailing them mid-checkout looks pushy and creates confusion if they do convert.

Add a **Wait** node after the Webhook. Set it to **1 hour** (or 30 minutes for faster-moving products). The workflow suspends here — no polling, no memory usage — and resumes automatically when the timer fires.

---

## Step 3 — Check whether the order was placed in the meantime

**Node: HTTP Request + IF**

Before sending anything, verify the cart is still abandoned. Use the **HTTP Request** node to call the Shopify REST API:

```
GET https://{{$node["Webhook"].json.domain}}/admin/api/2024-07/checkouts/{{$node["Webhook"].json.token}}.json
```

Add your Shopify API credentials (Admin API access token) in the **Header Auth** credential. The response includes a `completed_at` field — it's `null` if the cart is still open, or a timestamp if the order went through.

Add an **IF** node:

- Condition: `{{$node["HTTP Request"].json.checkout.completed_at}}` is **empty**
- True branch → continue to email
- False branch → **NoOp** (do nothing, order was placed)

This prevents you from emailing someone who already bought.

---

## Step 4 — Let the AI write a personalized email

**Node: AI / LLM**

This is where generic tools fall short. Instead of a fixed template, you give the LLM the cart contents and ask it to write something specific and useful.

Add a **Basic LLM Chain** node (under the AI section). In the **System Message**, put something like:

```
You are a friendly email copywriter for an e-commerce brand.
Write a short, warm abandoned-cart recovery email.
Be specific about the products. No hard-sell language.
Include a clear call-to-action at the end. Max 120 words.
```

In the **User Message**, use an expression that pulls the actual cart data:

```
The customer {{$node["Webhook"].json.email}} left these items:

{{$node["Webhook"].json.line_items.map(i => `- ${i.title} x${i.quantity} ($${i.price})`).join('\n')}}

Cart total: ${{$node["Webhook"].json.subtotal_price}}
Recovery link: {{$node["Webhook"].json.abandoned_checkout_url}}

Write the email.
```

The AI output is a natural, product-aware win-back message — different for a customer who left $12 of face wash than for someone who left $380 of camera gear.

---

## Step 5 — Send the email

**Node: Send Email (SMTP) or Gmail**

Add a **Send Email** node (or the **Gmail** node if you prefer OAuth). Wire it up:

- **To**: `{{$node["Webhook"].json.email}}`
- **Subject**: something like `Still thinking it over?` or use another short AI call to generate a subject line
- **Body (HTML)**: `{{$node["LLM"].json.text}}`
- **From**: your store's sender address

For SMTP, you'll need your email provider credentials (Gmail app password, SendGrid, Brevo, etc.) stored in an n8n credential. The node stays generic — you're just pointing it at your existing email infrastructure.

---

## Handling edge cases

**Duplicate triggers**: Shopify can fire `checkouts/update` multiple times. Add a **Set** node early in the flow to extract the cart `token`, then use n8n's built-in **Deduplication** node (available in recent n8n versions) keyed on that token. Only the first event per token proceeds.

**Unsubscribed customers**: If you maintain a suppression list in a Google Sheet or Airtable, add an **HTTP Request** (or native node) to check it before the Wait step. If the customer is on the list, route to NoOp.

**Test with a real checkout**: Shopify's webhook test tool sends a sample payload but it won't have a real `abandoned_checkout_url`. Do one real checkout-dropout on your store (use a personal email) to see the actual payload shape before going live.

---

## Run this on AgentRoost — no DevOps required

Building this locally means managing Docker, SSL certificates, a public hostname for the Shopify webhook, uptime monitoring, and your own OpenAI API key. All of that adds up before you've sent a single recovery email.

On AgentRoost, you get your own n8n instance — your login, your workflows, your data — running 24/7 on a public subdomain (`https://<your-id>.agentroost.app`). The AI/LLM nodes are already wired to included credits. You don't create an OpenAI account, you don't enter an API key, you don't monitor usage dashboards. The AI node just works.

**How to set it up:**

1. Sign up at [agentroost.app](/en/pricing) — from $19.99/mo, 14-day money-back guarantee.
2. Create a new workspace, pick the **n8n** framework, give it a name.
3. Your private n8n editor opens at `https://<your-id>.agentroost.app` within about 2 minutes.
4. Import or build the workflow above. The Webhook node's URL is already public HTTPS — paste it into Shopify immediately.
5. Activate the workflow. It runs 24/7 without you keeping a laptop open.

The included AI credits cover the LLM calls for email generation. As your volume grows, Plus and Pro tiers add more compute and more included credits. [Compare plans](/en/pricing) to see what fits your store's size.

---

## Tips to improve recovery rate

- **Timing matters more than copy.** 1 hour is a good start; test 30 min vs. 2 hr to find your store's sweet spot.
- **Product images in the email** require HTML templating — pull the `line_items[].image` URLs from the Shopify payload and add them to an HTML body template instead of plain text output from the AI.
- **Second follow-up (optional)**: add a second branch 24 hours later that checks again and sends a shorter "last chance" email if still no order. Keep it to a maximum of 2 emails per cart — more than that starts hurting sender reputation.
- **UTM-tag the recovery link**: append `?utm_source=email&utm_medium=cart-recovery&utm_campaign=abandonment` to `abandoned_checkout_url` so you can track recovery conversions in Google Analytics separately from organic traffic.
