You already know that repeat and add-on sales are where the margin lives, yet most stores stop talking to a customer the moment the order confirmation goes out. A Shopify AI product recommendation email built in n8n fixes that gap without a paid upsell app. Every new order triggers a workflow that reads what the shopper bought, gathers other products from the same category, and lets Google Gemini choose the three that pair best, then emails them a clean “you might also like” pick.
Prefer to skip the setup? Grab the ready-made template below and be running in under ten minutes.
A Shopify AI product recommendation email built in n8n turns every new order into a personalized cross-sell. When an order arrives, the workflow reads what the customer bought, pulls other products from the same category, and lets Google Gemini pick three complementary items to feature in a follow-up email. It runs on free tiers, sends through Gmail, and never invents products, because it can only choose from your real catalog.
What it does
The workflow watches your store for new orders. The instant one is placed, it looks up the product that was purchased, finds sibling products in the same product_type, and hands that shortlist to Gemini with one job: pick the three items that complement the purchase and write a one-line reason for each. Those three products get dropped into an email template and sent to the customer through Gmail.
The result is a recommendation email that feels hand-picked rather than random. Because the candidate list is scoped to a single category and comes straight from your Shopify catalog, every suggestion is a product you actually sell and can actually ship.
┌──────────────────────────────────────────────────────────────┐ │ SHOPIFY AI PRODUCT RECOMMENDATION EMAIL │ │ │ │ [Order placed] │ │ ↓ │ │ [Shopify Trigger] → [Get purchased product] → │ │ [Get same-category products] → [Build candidates] → │ │ [Gemini picks 3] → [Build email] → [Gmail send] │ └──────────────────────────────────────────────────────────────┘
Why it beats the default
Shopify’s built-in “related products” block on a product page is passive. It only helps a shopper who is already browsing, and it disappears the moment they check out. Paid recommendation apps close that gap but add a monthly fee and often a percentage of revenue on top.
This n8n approach reaches the customer in their inbox, right after a purchase, when intent is highest and the brand is fresh in mind. You control the category logic, the email copy, and the send timing. There is no per-order fee, no shared revenue, and no third-party script slowing your storefront. For the broader picture of what else you can wire up this way, see our guide to Shopify automation with n8n.
What you need
- A running n8n instance, either n8n Cloud or self-hosted.
- A Shopify store with Admin API access. If you have not connected n8n to Shopify yet, follow our 2026 Shopify to n8n connection guide, which covers the current Dev Dashboard method.
- A Google Gemini API key on the free tier, using the
gemini-2.5-flashmodel. - A Gmail account connected to n8n for sending the emails.
Build time is around 30 to 45 minutes from scratch, or under ten minutes if you import the template.
Node-by-node list
Seven nodes carry an order from placed to recommendation email.
- Shopify Trigger fires on the
orders/createtopic the moment a new order is placed. - An HTTP Request node reads the purchased product so the workflow knows its
product_type. - A second HTTP Request node pulls other active products in that same
product_type. - A Code node trims the list into clean candidates, removes the item that was just bought, and attaches the customer name and email.
- An HTTP Request node calls Gemini and asks it to pick the three best matches as JSON.
- A Code node parses Gemini’s answer and builds the email HTML.
- A Gmail node sends the recommendation email to the customer.
Step-by-step build
1 Shopify Trigger (orders/create)
Add a Shopify Trigger node and set the topic to Order Created. Attach your Shopify Access Token credential. This node hands the full order object to the rest of the workflow. The fields that matter here are the first line item’s product_id and the customer block.
{
"id": 5123400012345,
"customer": { "first_name": "Emily", "email": "emily.rodriguez@gmail.com" },
"line_items": [
{ "product_id": 7781234500001, "title": "Cedar & Sage Candle", "price": "28.00" }
]
}
The old Shopify admin custom-app screen is gone. Create your app in the Shopify Dev Dashboard, grant the read_products and read_orders scopes, and paste the access token into n8n. The connection guide has the exact clicks.
2 Get purchased product (HTTP Request)
Order line items do not include the product category, so fetch the product directly. Use an HTTP Request node with the GET method and your Shopify credential as a predefined credential type.
GET https://YOUR_STORE.myshopify.com/admin/api/2026-04/products/{{ $json.line_items[0].product_id }}.json
The response gives you product.product_type, for example Candles, which becomes the filter for the next step.
3 Get same-category products (HTTP Request)
Now pull a shortlist of sibling products. Another GET request filters the catalog by the category you just found and limits the pool so Gemini has a focused set to rank.
GET https://YOUR_STORE.myshopify.com/admin/api/2026-04/products.json?product_type={{ encodeURIComponent($json.product.product_type) }}&status=active&limit=15
Scoping candidates to one product_type is what keeps recommendations sensible. A candle buyer sees wick trimmers and matches, not phone cases. If your catalog uses collections instead of product types, swap this call for a collection products endpoint.
4 Build candidates (Code)
Add a Code node to turn the raw product payload into a tidy list. It strips each product down to the fields Gemini needs, drops the item that was just purchased, and carries the customer details forward.
const purchasedId = $('Shopify Trigger').item.json.line_items[0].product_id;
const products = $json.products || [];
const candidates = products
.filter(p => p.id !== purchasedId)
.slice(0, 12)
.map(p => ({
title: p.title,
handle: p.handle,
price: p.variants?.[0]?.price || "",
type: p.product_type
}));
const c = $('Shopify Trigger').item.json.customer;
return [{ json: {
firstName: c.first_name,
email: c.email,
purchased: $('Shopify Trigger').item.json.line_items[0].title,
candidates
} }];
5 Gemini picks three (HTTP Request)
This is where the AI earns its keep. Add an HTTP Request node with the POST method pointing at the Gemini endpoint. Set the body type to JSON and paste a JSON body that includes the candidate list and a strict instruction. Attach your Gemini key as an HTTP Header Auth credential using the header x-goog-api-key.
POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
{
"contents": [{
"parts": [{
"text": "The customer bought: {{ $json.purchased }}. From ONLY this JSON list of products, choose the 3 that best complement the purchase. Never invent products. Return JSON array of {title, handle, reason}. Products: {{ JSON.stringify($json.candidates) }}"
}]
}],
"generationConfig": { "responseMimeType": "application/json", "temperature": 0.4 }
}
In the HTTP Request node, set Specify Body to Using JSON and place the object above in the JSON field. Setting responseMimeType to application/json forces Gemini to answer with parseable JSON instead of prose.
6 Build the email (Code)
Gemini returns its answer nested inside the API response. This Code node digs it out, parses it, and assembles simple product cards into an HTML email body.
const raw = $json.candidates[0].content.parts[0].text;
const picks = JSON.parse(raw);
const store = "https://your-store.com/products/";
const cards = picks.map(p =>
`<p><a href="${store}${p.handle}">${p.title}</a> - ${p.reason}</p>`
).join("");
const first = $('Build candidates').item.json.firstName;
return [{ json: {
to: $('Build candidates').item.json.email,
subject: `${first}, three things that pair with your order`,
html: `<p>Hi ${first},</p><p>Thanks for your order. You might also like:</p>${cards}`
} }];
7 Send with Gmail
Finish with a Gmail node set to Send. Map To to {{ $json.to }}, Subject to {{ $json.subject }}, and the message to {{ $json.html }} with the email type set to HTML. Save the workflow and switch it on.
Common mistakes
| Symptom | Likely cause | Fix |
|---|---|---|
| Email lists a product you do not sell | Gemini was allowed to free-write | Keep responseMimeType as JSON and parse the array; never send raw model text into the email |
| No candidates found | The purchased product has no product_type set |
Add a fallback that queries your best-sellers collection when the type is empty |
| 401 from the Shopify calls | Missing read_products scope on the app |
Add the scope in the Dev Dashboard and reinstall the token |
| Gemini returns text, not JSON | responseMimeType not set on the request |
Add it under generationConfig in the JSON body |
| Email never arrives | Gmail node using the wrong content type | Set the email type to HTML so the product links render |
Cost at realistic volume
Take a store doing 600 orders a month. That is 600 recommendation emails, each making one Gemini call on gemini-2.5-flash. The Gemini free tier comfortably covers that volume, so the AI cost is zero. Self-hosted n8n is free and one order triggers a handful of lightweight executions. Gmail sends within its normal daily limits at this scale.
| Component | Cost at 600 orders/month |
|---|---|
| n8n (self-hosted) | Server time only, effectively free |
| Google Gemini (gemini-2.5-flash) | Free tier |
| Gmail sending | Included |
| Shopify Admin API calls | Free, well within rate limits |
Compare that to a paid recommendation app charging a monthly fee plus a slice of attributed revenue, and the workflow pays for itself on the first recovered add-on sale.
🚀 Get the ready-to-import template
The guide above is free to follow. If you would rather skip the build, download the ready-to-import workflow, then just add your credentials. Prefer it installed and tuned for you? See our done-for-you services.
Instant download · Works on n8n Cloud and self-hosted
Frequently asked questions
Will the AI ever recommend products I do not sell?
No. The workflow only sends Gemini a list of real products pulled from your own Shopify catalog, and the prompt tells it to choose only from that list. A parsing step also drops any item outside the candidate set, so the email can never feature a product that does not exist in your store.
Does this cost anything to run?
For most small and mid-size stores it runs on free tiers. Self-hosted n8n is free, Google Gemini has a free tier that covers thousands of recommendation emails a month, and Gmail sends the messages. Your only real cost is the small amount of server time to keep n8n running.
How does it pick complementary items?
It fetches other products from the same product_type as the item that was purchased, then asks Gemini to rank the three that pair best with the order. Because the candidate pool is scoped to one category, the suggestions stay relevant instead of drifting into unrelated parts of your catalog.
Can I send it a few days after purchase instead of instantly?
Yes. Add a Wait node after the Gmail step, or switch the trigger to a daily Schedule that queries orders from three days ago. A delayed send often performs better because the customer has received the first product and is ready to consider a companion item.
Do I need the Shopify custom app flow to connect n8n?
No. Shopify retired the old admin custom-app screen. In 2026 you create an app in the Shopify Dev Dashboard, assign Admin API scopes, and paste the access token into n8n. Our connection guide walks through the exact steps and required scopes.