AutomationFlowsE-commerce › Recover Shopify Abandoned Carts and Send Weekly Reports via Gmail and Sheets

Recover Shopify Abandoned Carts and Send Weekly Reports via Gmail and Sheets

ByMuhammed Umar @umarimran1234 on n8n.io

This template automates Shopify abandoned cart recovery with a 3-email Gmail sequence, tracks recoveries in Google Sheets via Shopify “order paid” webhooks, and sends a weekly HTML performance report every Monday using data aggregated from the same spreadsheet. Receives a…

Cron / scheduled trigger★★★★★ complexity49 nodesGoogle SheetsGmailHTTP Request
E-commerce Trigger: Cron / scheduled Nodes: 49 Complexity: ★★★★★ Added:
Recover Shopify Abandoned Carts and Send Weekly Reports via Gmail and Sheets — n8n workflow card showing Google Sheets, Gmail, HTTP Request integration

This workflow corresponds to n8n.io template #17196 — we link there as the canonical source.

This workflow follows the Gmail → Google Sheets recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "z0yxkbFL31ufp3Ru",
  "name": "Shopify Abandoned Cart Recovery \u2014 Complete System",
  "tags": [],
  "nodes": [
    {
      "id": "fbe7d505-e692-4c90-8018-e60486ca0109",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 480,
        "height": 896,
        "content": "## Shopify Abandoned Cart Recovery \u2014 Complete System\n\n### How it works\n\nThis workflow runs a complete Shopify abandoned cart recovery system. It captures new checkout events, deduplicates them in Google Sheets, sends a timed three-email recovery sequence, and checks Shopify before each email to stop messaging customers who already purchased. A separate paid-order webhook marks recovered carts, while a scheduled Monday report emails weekly recovery statistics.\n\n### Setup steps\n\n- Create and connect Shopify webhooks for checkout-created and order-paid events to the two n8n Webhook trigger URLs.\n- Configure Shopify Admin API access for the HTTP Request nodes that check orders and create price rules/discount codes.\n- Connect Google Sheets credentials and map all sheet nodes to the correct spreadsheet, worksheet, lookup columns, and status fields.\n- Connect Gmail credentials and set the sender, recipients, subject lines, and email body templates for all recovery and reporting emails.\n- Verify the schedule trigger timezone for the Monday 9AM report and test the full flow with a test checkout and test paid order.\n\n### Customization\n\nAdjust the wait durations, email copy, discount amount/rules, duplicate detection logic, report metrics, and Google Sheets columns to match the store\u2019s recovery strategy."
      },
      "typeVersion": 1
    },
    {
      "id": "10dca95e-5dbb-4208-aa44-b32e59b44726",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3488,
        720
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 432,
        "content": "## Checkout intake validation\n\nReceives Shopify checkout-created events, confirms a customer email is present, and searches the tracking sheet for an existing cart record."
      },
      "typeVersion": 1
    },
    {
      "id": "41323ca4-6b49-4154-8670-f907a0fc037d",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4160,
        720
      ],
      "parameters": {
        "color": 7,
        "width": 848,
        "height": 416,
        "content": "## Deduplicate and log cart\n\nDetermines whether a recovery sequence is already active, skips duplicates, extracts cart details, and logs new abandoned cart records to Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "d404acff-5977-423f-b6e8-b1802efe0ab0",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5040,
        720
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 416,
        "content": "## First purchase check\n\nWaits one hour after logging the cart, queries Shopify for an order, and branches based on whether the customer already purchased."
      },
      "typeVersion": 1
    },
    {
      "id": "73d8efe5-f274-4d06-b93d-4880c0f94227",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5696,
        720
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 416,
        "content": "## First reminder follow-up\n\nSends the first reminder email, records that Email 1 was sent in the sheet, then waits until the 24-hour follow-up point."
      },
      "typeVersion": 1
    },
    {
      "id": "45f72542-4791-4e9b-943f-33ad9dd30694",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6352,
        688
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 448,
        "content": "## Second purchase check\n\nChecks Shopify again around 24 hours after checkout and only continues to the urgency email if no purchase is found."
      },
      "typeVersion": 1
    },
    {
      "id": "98e342a9-1b1a-488e-97b7-e44a8b6ed6c2",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6800,
        720
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 432,
        "content": "## Second urgency follow-up\n\nSends the second urgency email, updates the sheet with Email 2 status, and waits another 48 hours before the final offer stage."
      },
      "typeVersion": 1
    },
    {
      "id": "20c2d2a5-ca89-45c4-866d-523a1595cde9",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        7456,
        720
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 384,
        "content": "## Final purchase check\n\nPerforms the 72-hour purchase check and, if the cart is still unrecovered, generates a unique discount code for the final email."
      },
      "typeVersion": 1
    },
    {
      "id": "d718d09f-cb6f-4326-9703-b2044faec36f",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        8112,
        720
      ],
      "parameters": {
        "color": 7,
        "width": 848,
        "height": 464,
        "content": "## Create discount offer\n\nCreates the Shopify price rule and discount code, sends the final discount offer email, and records Email 3 as sent in Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "e807bcbb-c2df-45e4-9d0c-7d200a7837d9",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        496
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 352,
        "content": "## Paid order intake\n\nReceives Shopify order-paid events, extracts the order payload, and verifies that the order has an email address usable for matching."
      },
      "typeVersion": 1
    },
    {
      "id": "5f2ecff8-991b-41f8-9550-bf2336eb66fe",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1232,
        464
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 368,
        "content": "## Match recovered customer\n\nLooks up the buyer in the abandoned cart sheet, confirms whether the paid order belongs to a tracked recovery sequence, and prepares recovery metrics."
      },
      "typeVersion": 1
    },
    {
      "id": "b4190444-2a89-4239-89c4-7093a909ee5f",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1888,
        416
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 448,
        "content": "## Mark cart recovered\n\nUpdates the corresponding Google Sheets row to mark the abandoned cart as recovered after a paid order is matched."
      },
      "typeVersion": 1
    },
    {
      "id": "0a93cc24-6ded-485d-91a8-93614552af1b",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3152,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 400,
        "content": "## Weekly performance report\n\nRuns every Monday morning, retrieves all abandoned cart rows, calculates weekly recovery statistics, and emails the summary report."
      },
      "typeVersion": 1
    },
    {
      "id": "bf45c199-1921-40a8-989e-3d6e012e81db",
      "name": "Weekly Trigger at 9 AM Monday",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        3200,
        192
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "072a3859-4605-44b8-b72f-d69c909a7df4",
      "name": "Retrieve Abandoned Cart Records",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3424,
        192
      ],
      "parameters": {
        "operation": "getAll",
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit?usp=drivesdk",
          "cachedResultName": "Abondant"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "54875dec-1323-422f-8c11-f295740a0783",
      "name": "Compute Weekly Abandoned Cart Stats",
      "type": "n8n-nodes-base.code",
      "position": [
        3648,
        192
      ],
      "parameters": {
        "jsCode": "const allRows = $input.all();\nconst now = new Date();\nconst oneWeekAgo = new Date();\noneWeekAgo.setDate(oneWeekAgo.getDate() - 7);\nconst weekRows = allRows.filter(item => {\n  const row = item.json;\n  if (!row.abandoned_at) return false;\n  const abandonedDate = new Date(row.abandoned_at);\n  return abandonedDate >= oneWeekAgo && abandonedDate <= now;\n});\nconst totalAbandoned = weekRows.length;\nconst totalRecovered = weekRows.filter(r => r.json.recovered === 'TRUE').length;\nconst recoveryRate = totalAbandoned > 0 ? ((totalRecovered / totalAbandoned) * 100).toFixed(1) : 0;\nconst totalRevenueLost = weekRows.reduce((sum, r) => sum + parseFloat(r.json.cart_total || 0), 0);\nconst totalRevenueRecovered = weekRows.filter(r => r.json.recovered === 'TRUE').reduce((sum, r) => sum + parseFloat(r.json.recovery_revenue || 0), 0);\nconst email1Count = weekRows.filter(r => r.json.email1_sent === 'TRUE').length;\nconst email2Count = weekRows.filter(r => r.json.email2_sent === 'TRUE').length;\nconst email3Count = weekRows.filter(r => r.json.email3_sent === 'TRUE').length;\nconst recoveredViaEmail1 = weekRows.filter(r => r.json.recovered === 'TRUE' && r.json.recovered_via === 'email1_reminder').length;\nconst recoveredViaEmail2 = weekRows.filter(r => r.json.recovered === 'TRUE' && r.json.recovered_via === 'email2_urgency').length;\nconst recoveredViaEmail3 = weekRows.filter(r => r.json.recovered === 'TRUE' && r.json.recovered_via === 'email3_discount').length;\nlet bestEmail = 'None';\nconst maxRecoveries = Math.max(recoveredViaEmail1, recoveredViaEmail2, recoveredViaEmail3);\nif (maxRecoveries > 0) {\n  if (maxRecoveries === recoveredViaEmail1) bestEmail = 'Email 1 (Reminder)';\n  else if (maxRecoveries === recoveredViaEmail2) bestEmail = 'Email 2 (Urgency)';\n  else bestEmail = 'Email 3 (Discount)';\n}\nconst weekStart = oneWeekAgo.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\nconst weekEnd = now.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });\nreturn [{ json: { week_range: `${weekStart} \u2013 ${weekEnd}`, total_abandoned: totalAbandoned, total_recovered: totalRecovered, recovery_rate: recoveryRate, total_revenue_at_risk: totalRevenueLost.toFixed(2), total_revenue_recovered: totalRevenueRecovered.toFixed(2), email1_sent: email1Count, email2_sent: email2Count, email3_sent: email3Count, total_emails_sent: email1Count + email2Count + email3Count, recovered_via_email1: recoveredViaEmail1, recovered_via_email2: recoveredViaEmail2, recovered_via_email3: recoveredViaEmail3, best_performing_email: bestEmail } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "fe3535ec-5419-4ebf-ad04-7f1b88cbf4f1",
      "name": "Dispatch Weekly Report Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3872,
        192
      ],
      "parameters": {
        "sendTo": "REPLACE_WITH_MERCHANT_EMAIL",
        "message": "=<div style=\"font-family: Arial, sans-serif; max-width: 650px; margin: 0 auto; color: #333;\">\n  <div style=\"background: #008060; padding: 24px; border-radius: 8px 8px 0 0;\">\n    <h1 style=\"color: white; margin: 0; font-size: 22px;\">\ud83d\udcca Weekly Cart Recovery Report</h1>\n    <p style=\"color: rgba(255,255,255,0.8); margin: 8px 0 0;\">{{ $json.week_range }}</p>\n  </div>\n  <div style=\"background: #f9f9f9; padding: 24px; border-radius: 0 0 8px 8px;\">\n    <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 24px;\">\n      <div style=\"background: white; padding: 16px; border-radius: 8px; border-left: 4px solid #e63946; text-align: center;\">\n        <p style=\"margin: 0; font-size: 12px; color: #666; text-transform: uppercase;\">Carts Abandoned</p>\n        <h2 style=\"margin: 8px 0 0; font-size: 32px; color: #e63946;\">{{ $json.total_abandoned }}</h2>\n      </div>\n      <div style=\"background: white; padding: 16px; border-radius: 8px; border-left: 4px solid #008060; text-align: center;\">\n        <p style=\"margin: 0; font-size: 12px; color: #666; text-transform: uppercase;\">Recovered</p>\n        <h2 style=\"margin: 8px 0 0; font-size: 32px; color: #008060;\">{{ $json.total_recovered }}</h2>\n      </div>\n      <div style=\"background: white; padding: 16px; border-radius: 8px; border-left: 4px solid #f4a261; text-align: center;\">\n        <p style=\"margin: 0; font-size: 12px; color: #666; text-transform: uppercase;\">Recovery Rate</p>\n        <h2 style=\"margin: 8px 0 0; font-size: 32px; color: #f4a261;\">{{ $json.recovery_rate }}%</h2>\n      </div>\n      <div style=\"background: white; padding: 16px; border-radius: 8px; border-left: 4px solid #2a9d8f; text-align: center;\">\n        <p style=\"margin: 0; font-size: 12px; color: #666; text-transform: uppercase;\">Revenue Recovered</p>\n        <h2 style=\"margin: 8px 0 0; font-size: 32px; color: #2a9d8f;\">${{ $json.total_revenue_recovered }}</h2>\n      </div>\n    </div>\n    <div style=\"background: white; padding: 16px; border-radius: 8px; margin-bottom: 16px;\">\n      <h3 style=\"margin: 0 0 12px; font-size: 16px;\">\ud83d\udcb0 Revenue Summary</h3>\n      <table style=\"width: 100%; border-collapse: collapse;\">\n        <tr style=\"border-bottom: 1px solid #eee;\"><td style=\"padding: 8px 0; color: #666;\">Total revenue at risk</td><td style=\"padding: 8px 0; text-align: right; color: #e63946; font-weight: bold;\">${{ $json.total_revenue_at_risk }}</td></tr>\n        <tr style=\"border-bottom: 1px solid #eee;\"><td style=\"padding: 8px 0; color: #666;\">Revenue recovered</td><td style=\"padding: 8px 0; text-align: right; color: #008060; font-weight: bold;\">${{ $json.total_revenue_recovered }}</td></tr>\n        <tr><td style=\"padding: 8px 0; color: #666;\">Emails sent this week</td><td style=\"padding: 8px 0; text-align: right; font-weight: bold;\">{{ $json.total_emails_sent }}</td></tr>\n      </table>\n    </div>\n    <div style=\"background: white; padding: 16px; border-radius: 8px; margin-bottom: 16px;\">\n      <h3 style=\"margin: 0 0 12px; font-size: 16px;\">\ud83d\udce7 Email Sequence Performance</h3>\n      <table style=\"width: 100%; border-collapse: collapse;\">\n        <tr style=\"background: #f4f4f4;\"><th style=\"padding: 8px; text-align: left; font-size: 13px;\">Email</th><th style=\"padding: 8px; text-align: center; font-size: 13px;\">Sent</th><th style=\"padding: 8px; text-align: center; font-size: 13px;\">Recovered</th></tr>\n        <tr style=\"border-bottom: 1px solid #eee;\"><td style=\"padding: 8px;\">Email 1 \u2014 Reminder (1hr)</td><td style=\"padding: 8px; text-align: center;\">{{ $json.email1_sent }}</td><td style=\"padding: 8px; text-align: center; color: #008060; font-weight: bold;\">{{ $json.recovered_via_email1 }}</td></tr>\n        <tr style=\"border-bottom: 1px solid #eee;\"><td style=\"padding: 8px;\">Email 2 \u2014 Urgency (24hr)</td><td style=\"padding: 8px; text-align: center;\">{{ $json.email2_sent }}</td><td style=\"padding: 8px; text-align: center; color: #008060; font-weight: bold;\">{{ $json.recovered_via_email2 }}</td></tr>\n        <tr><td style=\"padding: 8px;\">Email 3 \u2014 Discount (72hr)</td><td style=\"padding: 8px; text-align: center;\">{{ $json.email3_sent }}</td><td style=\"padding: 8px; text-align: center; color: #008060; font-weight: bold;\">{{ $json.recovered_via_email3 }}</td></tr>\n      </table>\n      <p style=\"margin: 12px 0 0; font-size: 13px;\">\ud83c\udfc6 <strong>Best performing:</strong> {{ $json.best_performing_email }}</p>\n    </div>\n    <p style=\"font-size: 12px; color: #999; text-align: center; margin-top: 24px;\">This report is auto-generated every Monday. View full data in Google Sheets.</p>\n  </div>\n</div>",
        "options": {},
        "subject": "=\ud83d\udcca Weekly Cart Recovery Report \u2014 {{ $json.week_range }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "91c02639-9008-4517-97fb-599a6274592b",
      "name": "Order Paid Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [
        608,
        672
      ],
      "parameters": {
        "path": "shopify-order-paid",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2
    },
    {
      "id": "d2c15c31-e946-4f2d-99b2-06925409af23",
      "name": "Parse Order Information",
      "type": "n8n-nodes-base.code",
      "position": [
        832,
        672
      ],
      "parameters": {
        "jsCode": "const body = $input.first().json.body;\nconst email = body.email || body.customer?.email || '';\nconst orderTotal = body.total_price || '0';\nconst orderId = body.id || '';\nconst orderName = body.name || '';\nreturn [{ json: { order_email: email, order_total: orderTotal, order_id: orderId, order_name: orderName, paid_at: new Date().toISOString() } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "f3ef2637-290b-4a38-9526-d869edf595bd",
      "name": "Verify Email Presence",
      "type": "n8n-nodes-base.if",
      "position": [
        1056,
        656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-email",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.order_email }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "5f7df208-b995-415b-866d-902973c3cef5",
      "name": "Locate Abandoned Cart Entry",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1280,
        656
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.order_email }}",
              "lookupColumn": "customer_email"
            },
            {
              "lookupValue": "FALSE",
              "lookupColumn": "recovered"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit?usp=drivesdk",
          "cachedResultName": "Abondant"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "7706a6ae-3f43-43d3-8d60-0baf929da8ee",
      "name": "Confirm Abandoned Cart Customer",
      "type": "n8n-nodes-base.if",
      "position": [
        1488,
        656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "found-row",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.customer_email }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "f09f509d-0162-4023-8e63-eca826ba1329",
      "name": "Construct Recovery Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1712,
        656
      ],
      "parameters": {
        "jsCode": "const row = $input.first().json;\nconst orderData = $('Parse Order Information').first().json;\nlet recoveredVia = 'unknown';\nif (row.email3_sent === 'TRUE') { recoveredVia = 'email3_discount'; }\nelse if (row.email2_sent === 'TRUE') { recoveredVia = 'email2_urgency'; }\nelse if (row.email1_sent === 'TRUE') { recoveredVia = 'email1_reminder'; }\nreturn [{ json: { checkout_token: row.checkout_token, customer_email: row.customer_email, customer_name: row.customer_name, original_cart_total: row.cart_total, recovery_revenue: orderData.order_total, recovered_via: recoveredVia, recovered_at: new Date().toISOString(), order_id: orderData.order_id, order_name: orderData.order_name } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "a4bb0bd5-9e2b-46a9-abd4-ccc28d1e1861",
      "name": "Update Sheet for Recovered Cart",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2064,
        656
      ],
      "parameters": {
        "columns": {
          "value": {
            "recovered": "TRUE",
            "recovered_at": "={{ $json.recovered_at }}",
            "recovered_via": "={{ $json.recovered_via }}",
            "checkout_token": "={{ $json.checkout_token }}",
            "recovery_revenue": "={{ $json.recovery_revenue }}"
          },
          "schema": [
            {
              "id": "checkout_token",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "checkout_token",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recovered",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "recovered",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recovery_revenue",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "recovery_revenue",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recovered_via",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "recovered_via",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recovered_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "recovered_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "checkout_token"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit?usp=drivesdk",
          "cachedResultName": "Abondant"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "3a7763b0-57ef-491c-baf9-0afdea8ad799",
      "name": "Checkout Created Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [
        3536,
        944
      ],
      "parameters": {
        "path": "shopify-abandoned-cart",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2
    },
    {
      "id": "3124786b-8b19-46b1-9abc-b908fdb438a3",
      "name": "Check Customer Email Available",
      "type": "n8n-nodes-base.if",
      "position": [
        3760,
        944
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-email",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.body.email }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "623bce08-457e-4c26-9ce7-7f5860fe3671",
      "name": "Detect Duplicate in Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3984,
        944
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.body.email }}",
              "lookupColumn": "customer_email"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit?usp=drivesdk",
          "cachedResultName": "Abondant"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "d3931e88-4fd7-416c-bfc9-a5632424bf5c",
      "name": "Check Active Sequence",
      "type": "n8n-nodes-base.code",
      "position": [
        4208,
        944
      ],
      "parameters": {
        "jsCode": "const results = $input.all();\nif (!results || results.length === 0) {\n  return [{ json: { is_duplicate: false, reason: 'No existing sequence found' } }];\n}\nconst activeSequence = results.find(item => {\n  const row = item.json;\n  return row.email3_sent === 'FALSE' && row.recovered === 'FALSE';\n});\nif (activeSequence) {\n  return [{ json: { is_duplicate: true, reason: 'Active sequence already running', existing_token: activeSequence.json.checkout_token } }];\n}\nreturn [{ json: { is_duplicate: false, reason: 'Previous sequences completed' } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "265e0380-8a43-45a2-b164-80652ec92a68",
      "name": "Skip if Duplicate Detected",
      "type": "n8n-nodes-base.if",
      "position": [
        4416,
        944
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "not-duplicate",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.is_duplicate }}",
              "rightValue": false
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "463c9dce-2d65-4ca7-8278-2c6a22a31385",
      "name": "Extract Checkout Cart Data",
      "type": "n8n-nodes-base.code",
      "position": [
        4640,
        944
      ],
      "parameters": {
        "jsCode": "const body = $('Checkout Created Webhook Trigger').first().json.body;\nconst products = (body.line_items || []).map(item => `${item.title} x${item.quantity}`).join(', ');\nconst firstName = body.customer?.first_name || body.billing_address?.first_name || 'there';\nreturn [{ json: { checkout_token: body.token, customer_email: body.email, customer_name: firstName, cart_total: body.total_price, currency: body.currency || 'USD', products: products, abandoned_checkout_url: body.abandoned_checkout_url, shop_domain: body.domain || 'YOUR_SHOP.myshopify.com', abandoned_at: new Date().toISOString(), item_count: (body.line_items || []).length } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "6269439e-d9f9-4a48-b3f2-57e76c5675fc",
      "name": "Append Checkout Data to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4864,
        944
      ],
      "parameters": {
        "columns": {
          "value": {
            "currency": "={{ $json.currency }}",
            "products": "={{ $json.products }}",
            "recovered": "FALSE",
            "cart_total": "={{ $json.cart_total }}",
            "email1_sent": "FALSE",
            "email2_sent": "FALSE",
            "email3_sent": "FALSE",
            "abandoned_at": "={{ $json.abandoned_at }}",
            "customer_name": "={{ $json.customer_name }}",
            "checkout_token": "={{ $json.checkout_token }}",
            "customer_email": "={{ $json.customer_email }}",
            "recovery_revenue": "0"
          },
          "schema": [
            {
              "id": "checkout_token",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "checkout_token",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "customer_email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "customer_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "cart_total",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "cart_total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "currency",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "currency",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "products",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "products",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "abandoned_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "abandoned_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_sent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email1_sent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_sent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email2_sent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_sent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email3_sent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recovered",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "recovered",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recovery_revenue",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "recovery_revenue",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit?usp=drivesdk",
          "cachedResultName": "Abondant"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "0d329711-babd-425b-bbcd-5af63498780b",
      "name": "Wait 1 Hour for Follow-up",
      "type": "n8n-nodes-base.wait",
      "position": [
        5088,
        944
      ],
      "parameters": {
        "amount": 10
      },
      "typeVersion": 1.1
    },
    {
      "id": "86ccb94c-731a-4d45-9225-d7c5d57fb50d",
      "name": "Verify Order Pre-Email 1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        5296,
        944
      ],
      "parameters": {
        "url": "=https://testing-dcyurh1b.myshopify.com/admin/api/2024-01/orders.json",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "email",
              "value": "={{ $('Extract Checkout Cart Data').item.json.customer_email }}"
            },
            {
              "name": "status",
              "value": "any"
            },
            {
              "name": "financial_status",
              "value": "paid"
            },
            {
              "name": "limit",
              "value": "5"
            }
          ]
        },
        "nodeCredentialType": "shopifyApi"
      },
      "credentials": {
        "shopifyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "7ee51dab-83c8-465a-bfe9-763fd1f02eaf",
      "name": "Check Purchase Status (1hr)",
      "type": "n8n-nodes-base.if",
      "position": [
        5520,
        944
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "no-order",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.orders.length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "b2edb0b6-9482-4e15-99a8-4be686d87a3e",
      "name": "Dispatch Reminder Email 1",
      "type": "n8n-nodes-base.gmail",
      "position": [
        5744,
        944
      ],
      "parameters": {
        "sendTo": "={{ $('Extract Checkout Cart Data').item.json.customer_email }}",
        "message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n  <h2>Did you forget something? \ud83d\uded2</h2>\n  <p>Hi {{ $('Extract Checkout Cart Data').item.json.customer_name }},</p>\n  <p>We noticed you left some items in your cart. No worries \u2014 we saved them for you!</p>\n  <h3>Your Cart:</h3>\n  <p>{{ $('Extract Checkout Cart Data').item.json.products }}</p>\n  <p><strong>Total: {{ $('Extract Checkout Cart Data').item.json.currency }} {{ $('Extract Checkout Cart Data').item.json.cart_total }}</strong></p>\n  <br>\n  <a href=\"{{ $('Extract Checkout Cart Data').item.json.abandoned_checkout_url }}\" style=\"background-color: #008060; color: white; padding: 14px 28px; text-decoration: none; border-radius: 4px; display: inline-block;\">Complete My Order \u2192</a>\n  <br><br>\n  <p>If you have any questions, just reply to this email \u2014 we're happy to help!</p>\n  <p>\u2014 The Team</p>\n</div>",
        "options": {},
        "subject": "=\ud83d\udc4b Hey {{ $('Extract Checkout Cart Data').item.json.customer_name }}, you left something behind!"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "fabf04c0-9d12-4633-a993-972084d12ac2",
      "name": "Log Email 1 Sent in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        5968,
        944
      ],
      "parameters": {
        "columns": {
          "value": {
            "email1_sent": "TRUE",
            "checkout_token": "={{ $('Extract Checkout Cart Data').item.json.checkout_token }}"
          },
          "schema": [
            {
              "id": "checkout_token",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "checkout_token",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_sent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email1_sent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "checkout_token"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit?usp=drivesdk",
          "cachedResultName": "Abondant"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b85c789f-78eb-4e4c-93cf-37c40b079da2",
      "name": "Pause for 23 Hours",
      "type": "n8n-nodes-base.wait",
      "position": [
        6176,
        944
      ],
      "parameters": {
        "amount": 10
      },
      "typeVersion": 1.1
    },
    {
      "id": "2958621b-b0ee-4990-8de6-ba14dfefc4d2",
      "name": "Verify Order Pre-Email 2",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        6400,
        944
      ],
      "parameters": {
        "url": "=https://testing-dcyurh1b.myshopify.com/admin/api/2024-01/orders.json",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "email",
              "value": "={{ $('Extract Checkout Cart Data').item.json.customer_email }}"
            },
            {
              "name": "status",
              "value": "any"
            },
            {
              "name": "financial_status",
              "value": "paid"
            },
            {
              "name": "limit",
              "value": "5"
            }
          ]
        },
        "nodeCredentialType": "shopifyApi"
      },
      "credentials": {
        "shopifyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a6561a6f-e330-490c-9c23-74c4e8e686d7",
      "name": "Check Purchase Status (24hr)",
      "type": "n8n-nodes-base.if",
      "position": [
        6624,
        944
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "no-order-2",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.orders.length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "571737c9-1405-4b70-910b-231a81c1323f",
      "name": "Dispatch Urgency Email 2",
      "type": "n8n-nodes-base.gmail",
      "position": [
        6848,
        928
      ],
      "parameters": {
        "sendTo": "={{ $('Extract Checkout Cart Data').item.json.customer_email }}",
        "message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n  <h2>\u26a1 Items in your cart are going fast!</h2>\n  <p>Hi {{ $('Extract Checkout Cart Data').item.json.customer_name }},</p>\n  <p>The items you left in your cart are popular and stock is limited.</p>\n  <h3>Still in your cart:</h3>\n  <p>{{ $('Extract Checkout Cart Data').item.json.products }}</p>\n  <p><strong>Total: {{ $('Extract Checkout Cart Data').item.json.currency }} {{ $('Extract Checkout Cart Data').item.json.cart_total }}</strong></p>\n  <br>\n  <a href=\"{{ $('Extract Checkout Cart Data').item.json.abandoned_checkout_url }}\" style=\"background-color: #e63946; color: white; padding: 14px 28px; text-decoration: none; border-radius: 4px; display: inline-block;\">Secure My Order \u2192</a>\n  <br><br>\n  <p>\u2014 The Team</p>\n</div>",
        "options": {},
        "subject": "=\u26a1 {{ $('Extract Checkout Cart Data').item.json.customer_name }}, your cart is selling fast!"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5e89b53c-0cff-47eb-8c1d-80dfdac01587",
      "name": "Log Email 2 Sent in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        7056,
        944
      ],
      "parameters": {
        "columns": {
          "value": {
            "email2_sent": "TRUE",
            "checkout_token": "={{ $('Extract Checkout Cart Data').item.json.checkout_token }}"
          },
          "schema": [
            {
              "id": "checkout_token",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "checkout_token",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_sent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email2_sent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "checkout_token"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit?usp=drivesdk",
          "cachedResultName": "Abondant"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "4c7961c2-e6e3-48a4-b14f-ce5df42bd529",
      "name": "Pause for 48 Hours",
      "type": "n8n-nodes-base.wait",
      "position": [
        7280,
        944
      ],
      "parameters": {
        "amount": 10
      },
      "typeVersion": 1.1
    },
    {
      "id": "a55b93e1-44f7-4025-9e53-89ef206eaf95",
      "name": "Verify Order Pre-Email 3",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        7504,
        944
      ],
      "parameters": {
        "url": "=https://testing-dcyurh1b.myshopify.com/admin/api/2024-01/orders.json",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "email",
              "value": "={{ $('Extract Checkout Cart Data').item.json.customer_email }}"
            },
            {
              "name": "status",
              "value": "any"
            },
            {
              "name": "financial_status",
              "value": "paid"
            },
            {
              "name": "limit",
              "value": "5"
            }
          ]
        },
        "nodeCredentialType": "shopifyApi"
      },
      "credentials": {
        "shopifyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a52c2229-f573-41d1-847b-1488c27e7bb3",
      "name": "Check Purchase Status (72hr)",
      "type": "n8n-nodes-base.if",
      "position": [
        7728,
        944
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "no-order-3",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.orders.length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "fc0dff26-6c62-4b0b-9dc2-d5000d051698",
      "name": "Create Unique Discount Code",
      "type": "n8n-nodes-base.code",
      "position": [
        7936,
        928
      ],
      "parameters": {
        "jsCode": "const customerName = $('Extract Checkout Cart Data').item.json.customer_name;\nconst nameSlug = customerName.toUpperCase().replace(/[^A-Z]/g, '').slice(0, 4);\nconst random = Math.random().toString(36).substring(2, 7).toUpperCase();\nconst discountCode = `RECOVER-${nameSlug}-${random}`;\nconst expiresAt = new Date();\nexpiresAt.setHours(expiresAt.getHours() + 24);\nreturn [{ json: { ...$('Extract Checkout Cart Data').item.json, discount_code: discountCode, discount_expires_at: expiresAt.toISOString(), discount_percent: 10 } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "966974c8-7545-4bbc-9fd6-0d05f33ce3f7",
      "name": "Set Price Rule in Shopify",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        8160,
        960
      ],
      "parameters": {
        "url": "https://testing-dcyurh1b.myshopify.com/admin/api/2024-01/price_rules.json",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"price_rule\": {\n    \"title\": \"{{ $json.discount_code }}\",\n    \"target_type\": \"line_item\",\n    \"target_selection\": \"all\",\n    \"allocation_method\": \"across\",\n    \"value_type\": \"percentage\",\n    \"value\": \"-10.0\",\n    \"customer_selection\": \"all\",\n    \"starts_at\": \"{{ $now.toISO() }}\",\n    \"ends_at\": \"{{ $json.discount_expires_at }}\",\n    \"usage_limit\": 1,\n    \"once_per_customer\": true\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "shopifyApi"
      },
      "credentials": {
        "shopifyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9850846b-a902-4d6f-8aac-d4550a1aa74f",
      "name": "Establish Discount Code in Shopify",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        8384,
        976
      ],
      "parameters": {
        "url": "=https://testing-dcyurh1b.myshopify.com/admin/api/2024-01/price_rules/{{ $json.price_rule.id }}/discount_codes.json",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"discount_code\": {\n    \"code\": \"{{ $('Create Unique Discount Code').item.json.discount_code }}\"\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "shopifyApi"
      },
      "credentials": {
        "shopifyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "878eb469-ddd3-4f92-b4dc-55a10ad61271",
      "name": "Dispatch Discount Offer Email 3",
      "type": "n8n-nodes-base.gmail",
      "position": [
        8608,
        976
      ],
      "parameters": {
        "sendTo": "={{ $('Extract Checkout Cart Data').item.json.customer_email }}",
        "message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n  <h2>\ud83c\udf81 A special offer, just for you!</h2>\n  <p>Hi {{ $('Extract Checkout Cart Data').item.json.customer_name }},</p>\n  <p>Use the code below for <strong>10% off</strong>. Expires in 24 hours \u2014 single use only.</p>\n  <div style=\"background: #f4f4f4; padding: 20px; text-align: center; border-radius: 8px; margin: 20px 0;\">\n    <p style=\"margin: 0; font-size: 14px;\">Your exclusive one-time discount code:</p>\n    <h2 style=\"margin: 10px 0; color: #008060; letter-spacing: 4px;\">{{ $('Create Unique Discount Code').item.json.discount_code }}</h2>\n    <p style=\"margin: 0; font-size: 12px; color: #666;\">10% off \u2014 expires in 24 hours \u2014 single use only</p>\n  </div>\n  <h3>Still waiting for you:</h3>\n  <p>{{ $('Extract Checkout Cart Data').item.json.products }}</p>\n  <p><strong>Total: {{ $('Extract Checkout Cart Data').item.json.currency }} {{ $('Extract Checkout Cart Data').item.json.cart_total }}</strong></p>\n  <br>\n  <a href=\"{{ $('Extract Checkout Cart Data').item.json.abandoned_checkout_url }}\" style=\"background-color: #008060; color: white; padding: 14px 28px; text-decoration: none; border-radius: 4px; display: inline-block;\">Claim My 10% Discount \u2192</a>\n  <br><br>\n  <p style=\"font-size: 12px; color: #999;\">This is our final reminder.</p>\n  <p>\u2014 The Team</p>\n</div>",
        "options": {},
        "subject": "=\ud83c\udf81 {{ $('Extract Checkout Cart Data').item.json.customer_name }}, here's 10% off \u2014 just for you"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2e616552-476a-4b90-b836-2b5e7a9453b3",
      "name": "Log Email 3 Sent in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        8816,
        976
      ],
      "parameters": {
        "columns": {
          "value": {
            "email3_sent": "TRUE",
            "checkout_token": "={{ $('Extract Checkout Cart Data').item.json.checkout_token }}",
            "discount_code_used": "={{ $('Create Unique Discount Code').item.json.discount_code }}"
          },
          "schema": [
            {
              "id": "checkout_token",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "checkout_token",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_sent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email3_sent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "discount_code_used",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "discount_code_used",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "checkout_token"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o6rEojdVSqvXztw5IUifOGTK_zjR1AC3HWAzdJvFX90/edit?usp=drivesdk",
          "cachedResultName": "Abondant"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "7d89b90d-f53f-40ce-a2cd-4c4858c27036",
  "nodeGroups": [],
  "connections": {
    "Pause for 23 Hours": {
      "main": [
        [
          {
            "node": "Verify Order Pre-Email 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pause for 48 Hours": {
      "main": [
        [
          {
            "node": "Verify Order Pre-Email 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Active Sequence": {
      "main": [
        [
          {
            "node": "Skip if Duplicate Detected",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Email Presence": {
      "main": [
        [
          {
            "node": "Locate Abandoned Cart Entry",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Construct Recovery Data": {
      "main": [
        [
          {
            "node": "Update Sheet for Recovered Cart",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Order Information": {
      "main": [
        [
          {
            "node": "Verify Email Presence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dispatch Urgency Email 2": {
      "main": [
        [
          {
            "node": "Log Email 2 Sent in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Order Pre-Email 1": {
      "main": [
        [
          {
            "node": "Check Purchase Status (1hr)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Order Pre-Email 2": {
      "main": [
        [
          {
            "node": "Check Purchase Status (24hr)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Order Pre-Email 3": {
      "main": [
        [
          {
            "node": "Check Purchase Status (72hr)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Detect Duplicate in Sheet": {
      "main": [
        [
          {
            "node": "Check Active Sequence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dispatch Reminder Email 1": {
      "main": [
        [
          {
            "node": "Log Email 1 Sent in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Price Rule in Shopify": {
      "main": [
        [
          {
            "node": "Establish Discount Code in Shopify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 1 Hour for Follow-up": {
      "main": [
        [
          {
            "node": "Verify Order Pre-Email 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Checkout Cart Data": {
      "main": [
        [
          {
            "node": "Append Checkout Data to Sheets",
  

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This template automates Shopify abandoned cart recovery with a 3-email Gmail sequence, tracks recoveries in Google Sheets via Shopify “order paid” webhooks, and sends a weekly HTML performance report every Monday using data aggregated from the same spreadsheet. Receives a…

Source: https://n8n.io/workflows/17196/ — original creator credit. Request a take-down →

More E-commerce workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

E-commerce

This workflow automates inventory management and predictive reordering for Shopify stores. It integrates Shopify, Google Sheets, and Slack to monitor inventory levels, calculate dynamic reorder points

Shopify, Google Sheets, Gmail +2
E-commerce

A webhook or timer triggers the workflow to automatically fetch inventory data from multiple platforms. Stock levels are compared across stores to identify discrepancies, and any inconsistencies are u

HTTP Request, Google Sheets, Gmail
E-commerce

E-commerce store owners and sales managers who want AI-powered insights from their Shopify data without manually crunching numbers every week.

Shopify, HTTP Request, Slack +2
E-commerce

This n8n automation identifies Magento 2 orders that have been stuck in the same status (like "processing") for the past 7 weekdays (excluding weekends), compiles them into a clean Google Sheet report

HTTP Request, Google Sheets, Gmail
E-commerce

This n8n workflow automatically identifies customers who have abandoned their carts on your Shopify store, cleans and verifies their WhatsApp numbers, and sends them personalized reminders via the Rap

HTTP Request, Google Sheets