{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "ac1011ce-6d22-4dd7-89b1-4ed4e48fab02",
      "name": "\ud83d\uddfa\ufe0f Architecture Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2800,
        2848
      ],
      "parameters": {
        "width": 680,
        "height": 788,
        "content": "## \ud83d\uded2 Smart Shopping Assistant \u2013 WhatsApp Price Comparison Bot\n\n**3 independent pipelines \u2014 each does one job cleanly:**\n\n\ud83d\udce5 **PIPELINE A \u00b7 Intake**\nUser sends a list \u2192 OpenAI parses every item with qty/unit/category \u2192 saved to Google Sheets \u2192 confirmation sent\n\n\ud83d\udd0d **PIPELINE B \u00b7 Price Engine**\nUser sends *compare* \u2192 for each item: Serper searches live web prices \u2192 OpenAI picks best deal \u2192 full comparison card sent back\n\n\ud83d\udcec **PIPELINE C \u00b7 Alerts**\nSchedule runs daily 8AM \u2192 checks saved deals \u2192 sends personalised alert to any user with savings \u2265 10%\n\n---\n**Credentials:** WATI \u00b7 OpenAI Header Auth \u00b7 Serper Header Auth \u00b7 Google Sheets OAuth2\n**Serper:** free tier at serper.dev \u2013 2500 searches/month"
      },
      "typeVersion": 1
    },
    {
      "id": "aca804c2-dea9-4191-9aa3-74385356d50d",
      "name": "Pipeline A Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1840,
        4000
      ],
      "parameters": {
        "color": 7,
        "width": 444,
        "height": 760,
        "content": "Node: Wati Trigger1 & Intent Router1\nFunction: Captures incoming WhatsApp messages via Wati.Logic: The Switch node parses the {{ $json.text }} to determine what the user wants.\ncompare (Price check)\ndeals (View saved bargains)\nmylist (View shopping list)\nclear (Reset list)"
      },
      "typeVersion": 1
    },
    {
      "id": "1f7a04e3-de69-44bc-9121-582d38630b56",
      "name": "Pipeline B Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1264,
        4048
      ],
      "parameters": {
        "color": 7,
        "width": 1972,
        "height": 480,
        "content": "### \ud83d\udd0d Pipeline B \u00b7 Price Engine\n**Flow per item:**\n`Read List for Compare` \u2192 `Prepare Search Queries.`Serper \u2013 Search Prices`.`OpenAI \u2013 Extract Best Deal`.`Process Deal Result`.`Google Sheets \u2013 Save Deals`*(appends one row per item to Deals tab)*.`Aggregate Comparison Card`*(collects ALL items, calculates total, builds full card)*\u2193`Send a text message`\n*(sends full comparison card to user)*\n\n---\n\u26a0\ufe0f **Important:** n8n runs each item through the chain sequentially. The `Aggregate` node uses `$input.all()` to collect every item result before sending the final message."
      },
      "typeVersion": 1
    },
    {
      "id": "9ececa7a-15f6-45a6-9d1a-e9a5eea9ba0a",
      "name": "Pipeline C Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1104,
        4352
      ],
      "parameters": {
        "color": 7,
        "width": 1108,
        "height": 468,
        "content": "### \ud83d\udcec Pipeline C \u00b7 Daily Deal Alerts\nRuns automatically every day at 8:00 AM\n**Flow:**\nSchedule Trigger \u2013 Daily 8AM Alerts`.`Google Sheets \u2013 Read Deals for Alert`*(reads entire Deals tab)*.`Build Alert Messages`*(filters: alertSent = No AND savingPct \u2265 10)**(groups by phone, picks top 5 deals per user)**(returns one output item per user)*.`WATI \u2013 Send Deal Alert`*(sends personalised message to each user's phone)*\n---\n\u26a0\ufe0f **To-do after import:**\n- `alertSent` is not automatically updated to `Yes` after sending.\nAdd a `Google Sheets \u2013 Update` node after `Send Deal Alert` to set `alertSent = Yes` matching on `listId + item` to prevent duplicate alerts."
      },
      "typeVersion": 1
    },
    {
      "id": "275698cd-4f25-4c48-84e1-7a231a53186d",
      "name": "Intent Router1",
      "type": "n8n-nodes-base.switch",
      "position": [
        -1616,
        4256
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "New List",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "6517a435-aca0-4bfe-8c65-3e259a7e379c",
                    "operator": {
                      "type": "string",
                      "operation": "startsWith"
                    },
                    "leftValue": "={{ $json.text }}",
                    "rightValue": "list:"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Compare",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "49d5cdc0-9e0a-48fe-8635-0b5d2b42ef86",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.text.toLowerCase().trim() }}",
                    "rightValue": "compare"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "View Deals",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "a8d35ab2-6b29-4024-80d9-77cff7e1bc91",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.text.toLowerCase().trim() }}",
                    "rightValue": "deals"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "My List",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "f23b8525-5f8a-49e2-a7a8-baabf56293c4",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.text.toLowerCase().trim() }}",
                    "rightValue": "mylist"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Clear",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "282145b9-9654-4268-bc42-a7d37bcd6805",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.text.toLowerCase().trim() }}",
                    "rightValue": "clear"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "601d3afa-c9a2-439e-b735-6daf0875c582",
      "name": "OpenAI \u2013 Parse List1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1184,
        3696
      ],
      "parameters": {
        "url": "https://api.openai.com/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"gpt-4o-mini\",\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"You are a shopping assistant. Extract items from the user's text into a JSON array of objects with these keys: item, qty, unit, category. Categories: Grocery, Dairy, Produce, Meat, Beverages, Household, Personal Care, Electronics, Other. Return ONLY the JSON array.\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"{{ $('Wati Trigger').item.json.text }}\"\n    }\n  ],\n  \"temperature\": 0\n} ",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "openAiApi"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        },
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "8b36382e-cb67-458f-99cf-dbda4b432b69",
      "name": "Structure List Items1",
      "type": "n8n-nodes-base.code",
      "position": [
        -960,
        3696
      ],
      "parameters": {
        "jsCode": "// Structure Parsed Items \u2192 flat rows for Sheets\nconst phone    = $('Wati Trigger').first().json.waId || $('Wati Trigger1').item.json.from || 'unknown';\nconst userName = $('Wati Trigger').first().json.senderName || 'Shopper';\nconst now      = new Date();\nconst dateStr  = now.toISOString().split('T')[0].replace(/-/g, '');\nconst rand     = Math.random().toString(36).substring(2, 6).toUpperCase();\nconst listId   = `LST-${dateStr}-${rand}`;\n\nconst raw = $json?.choices?.[0]?.message?.content || '[]';\nlet items = [];\ntry { items = JSON.parse(raw); } catch(e) {\n  const m = raw.match(/\\[[\\s\\S]*\\]/);\n  if (m) { try { items = JSON.parse(m[0]); } catch(e2) {} }\n}\n\nif (!items || items.length === 0) {\n  return [{ json: {\n    phone, userName, listId, itemCount: 0, rows: [], isFirst: true,\n    ackMessage: `\u26a0\ufe0f Could not parse your list. Please try:\\n*list: milk 2L, eggs 12, bread, rice 5kg*`\n  }}];\n}\n\nconst rows = items.map(it => ({\n  listId, phone, userName,\n  item:     (it.item     || 'item').toLowerCase(),\n  qty:       it.qty      || 1,\n  unit:      it.unit     || 'pcs',\n  category:  it.category || 'Other',\n  addedAt:   now.toISOString(),\n  status:   'Active'\n}));\n\nconst catEmoji = { Grocery:'\ud83d\uded2\ufe0f', Dairy:'\ud83e\udd5b', Produce:'\ud83e\udd66', Meat:'\ud83e\udd69', Beverages:'\ud83e\udd64', Household:'\ud83c\udfe0', 'Personal Care':'\ud83e\uddf4', Electronics:'\ud83d\udcf1', Other:'\ud83d\udce6' };\n\nconst itemLines = items.map((it, i) =>\n  `  ${i+1}. ${catEmoji[it.category]||'\ud83d\udce6'} ${it.item} \u2014 ${it.qty} ${it.unit}`\n);\n\nconst ackMessage = [\n  `\u2705 *Shopping List Saved!*`,\n  `\ud83d\uddc2\ufe0f List ID: \\`${listId}\\``,\n  '',\n  `\ud83d\udce6 *${items.length} item${items.length > 1 ? 's' : ''} added:*`,\n  ...itemLines,\n  '',\n  '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501',\n  '\ud83d\udd0d Send *compare* \u2192 AI finds best prices now',\n  '\ud83d\udcb0 Send *deals* \u2192 view saved deals',\n  '\ud83d\udccb Send *mylist* \u2192 view current list'\n].join('\\n');\n\nreturn rows.map((row, i) => ({ json: { ...row, ackMessage: i === 0 ? ackMessage : null, isFirst: i === 0, phone, listId, itemCount: items.length } }));"
      },
      "typeVersion": 2
    },
    {
      "id": "e439642e-23db-4956-95ee-a1018058bb7a",
      "name": "Google Sheets \u2013 Save Shopping List1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -752,
        3696
      ],
      "parameters": {
        "columns": {
          "value": {
            "qty": "={{ $json.qty }}",
            "item": "={{ $json.item }}",
            "unit": "={{ $json.unit }}",
            "phone": "={{ $json.phone }}",
            "Status": "={{ $json.status }}",
            "listid": "={{ $json.listId }}",
            "addedAt": "={{ $json.addedAt }}",
            "category": "={{ $json.category }}",
            "username": "={{ $json.userName }}"
          },
          "schema": [
            {
              "id": "listid",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "listid",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "username",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "username",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "item",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "item",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "qty",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "qty",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "unit",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "unit",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "addedAt",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "addedAt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "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/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit#gid=0",
          "cachedResultName": "Shopping List"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit?usp=drivesdk",
          "cachedResultName": "Untitled spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "6f312e5e-4cc3-4e8a-85c7-f442635645a2",
      "name": "Google Sheets \u2013 Read My List1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1168,
        4704
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit#gid=0",
          "cachedResultName": "Shopping List"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit?usp=drivesdk",
          "cachedResultName": "Untitled spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "0bad7b13-b2e6-4c18-8e76-d719c78b1ee9",
      "name": "Build My List View1",
      "type": "n8n-nodes-base.code",
      "position": [
        -912,
        4704
      ],
      "parameters": {
        "jsCode": "const phone    = $('Wati Trigger').first().json.waId || $('Wati Trigger1').item.json.from;\nconst userName =  $('Wati Trigger').first().json.senderName|| 'Shopper';\nconst items    = $input.all().filter(r => r.json.phone === phone && (r.json.status||'').toLowerCase() === 'active');\n\nif (items.length === 0) {\n  return [{ json: { phone, msg: `\ud83d\udccb *Your list is empty, ${userName}!*\\n\\nAdd items with:\\n*list: milk 2L, eggs 12, bread, rice 5kg*` } }];\n}\n\nconst catEmoji = { Grocery:'\ud83d\uded2\ufe0f', Dairy:'\ud83e\udd5b', Produce:'\ud83e\udd66', Meat:'\ud83e\udd69', Beverages:'\ud83e\udd64', Household:'\ud83c\udfe0', 'Personal Care':'\ud83e\uddba', Electronics:'\ud83d\udcf1', Other:'\ud83d\udce6' };\nconst byCategory = {};\nfor (const r of items) {\n  const c = r.json.category || 'Other';\n  if (!byCategory[c]) byCategory[c] = [];\n  byCategory[c].push(r.json);\n}\n\nconst lines = [`\ud83d\udccb *Your Shopping List*`, `\ud83d\udc64 ${userName}`, ''];\nfor (const [cat, rows] of Object.entries(byCategory)) {\n  lines.push(`${catEmoji[cat]||'\ud83d\udce6'} *${cat}*`);\n  for (const it of rows) lines.push(`  \u2022 ${it.item} \u2014 ${it.qty} ${it.unit}`);\n  lines.push('');\n}\nlines.push(`\ud83d\udce6 *Total: ${items.length} items*`);\nlines.push('\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501');\nlines.push('Send *compare* to find best prices \ud83d\udd0d');\n\nreturn [{ json: { phone, msg: lines.join('\\n') } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "9c6454b9-afda-4888-a666-130b2d9fbc3a",
      "name": "Google Sheets \u2013 Read Saved Deals1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1184,
        5104
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1354101119,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit#gid=1354101119",
          "cachedResultName": "Deals"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit?usp=drivesdk",
          "cachedResultName": "Untitled spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b1a21a36-3c98-467a-b991-c96146670369",
      "name": "Build Deals View1",
      "type": "n8n-nodes-base.code",
      "position": [
        -864,
        5104
      ],
      "parameters": {
        "jsCode": "const phone    = $('Wati Trigger').first().json.waId || $('Wati Trigger1').item.json.from;\nconst userName = $('Wati Trigger').first().json.senderName || 'Shopper';\nconst allRows  = $input.all();\n\nconst myDeals = allRows.filter(r => r.json.phone === phone).sort((a,b)=>new Date(b.json.foundAt)-new Date(a.json.foundAt));\nconst seen = new Set();\nconst latest = myDeals.filter(r => { if (seen.has(r.json.item)) return false; seen.add(r.json.item); return true; });\n\nif (latest.length === 0) {\n  return [{ json: { phone, msg: `\ud83d\udcb0 *No saved deals yet, ${userName}!*\\n\\nSend *compare* to find the best prices for your list.` } }];\n}\n\nconst lines = [`\ud83d\udcb0 *Your Saved Deals*`, `\ud83d\udc64 ${userName}`, ''];\nfor (const r of latest) {\n  const saving = parseFloat($input.first().json.savingPct) > 0 ? ` \ud83c\udff7\ufe0f Save ${r.json.savingPct}%` : '';\n  const dt = r.json.foundAt ? new Date(r.json.foundAt).toLocaleDateString('en-IN',{day:'numeric',month:'short'}) : '';\n  lines.push(`\ud83d\uded2 *${r.json.item}*`);\n  lines.push(`  \u2705 ${r.json.storeName} \u2014 \u20b9${r.json.price}${saving}`);\n  if (r.json.url) lines.push(`  \ud83d\udd17 ${r.json.url}`);\n  lines.push(`  \ud83d\udcc5 Found: ${dt}`);\n  lines.push('');\n}\nlines.push('\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501');\nlines.push('Send *compare* to refresh prices \ud83d\udd04');\nreturn [{ json: { phone, msg: lines.join('\\n') } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "0da98dbc-8018-4c14-be6d-3091268a61be",
      "name": "Process Clear1",
      "type": "n8n-nodes-base.code",
      "position": [
        -1136,
        5504
      ],
      "parameters": {
        "jsCode": "const phone = $json.waId || $json.from;\nconst name  = $json.senderName || 'Shopper';\nreturn [{ json: { phone, msg: `\ud83d\uddd1\ufe0f *List cleared, ${name}!*\\n\\nStart fresh anytime:\\n*list: item1, item2, item3*` } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "e7d9692b-f8bb-4eac-98c6-5edc140c3961",
      "name": "Google Sheets \u2013 Read List for Compare1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1200,
        4352
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit#gid=0",
          "cachedResultName": "Shopping List"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit?usp=drivesdk",
          "cachedResultName": "Untitled spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "9508c89f-bc70-43b3-b576-7832139fb32a",
      "name": "Prepare Search Queries1",
      "type": "n8n-nodes-base.code",
      "position": [
        -928,
        4352
      ],
      "parameters": {
        "jsCode": "// Prepare one search query per item for this user\nconst phone =  $('Intent Router1').first().json.waId|| $('Wati Trigger1').item.json.from;\nconst rows  = $input.all().filter(r => r.json.phone === phone && (r.json.status||'').toLowerCase() === 'active');\n\nif (rows.length === 0) {\n  return [{ json: { phone, noItems: true, searchQuery: null,\n    errMsg: `\ud83d\udccb *Your list is empty!*\\n\\nAdd items first with: *list: milk 2L, eggs*`\n  }}];\n}\n\nreturn rows.map(r => ({\n  json: {\n    phone,\n    userName:    r.json.userName,\n    listId:      r.json.listId,\n    item:        r.json.item,\n    qty:         r.json.qty,\n    unit:        r.json.unit,\n    category:    r.json.category,\n    searchQuery: `best price ${r.json.item} ${r.json.qty}${r.json.unit} buy online India`,\n    noItems:     false\n  }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "9648270c-dc21-4ed1-9478-2d917ed38297",
      "name": "Serper \u2013 Search Prices1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -688,
        4352
      ],
      "parameters": {
        "url": "https://api.openai.com/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"gpt-4o-mini\",\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"You are a price comparison expert. Analyze the Google Shopping search results provided. 1. Identify the 'bestDeal' (lowest price from a reputable store). 2. Find up to 2 'alternatives'. 3. Calculate 'savingPct' if an original price is visible. 4. Return ONLY a JSON object with these keys: bestDeal (storeName, price, originalPrice, savingPct, url, currency), alternatives (array of storeName and price), confidence (high/low), and summary.\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"Search results for {{ $('Prepare Search Queries1').item.json.item }}: {{ JSON.stringify($json.shopping) }}\"\n    }\n  ],\n  \"response_format\": { \"type\": \"json_object\" },\n  \"temperature\": 0\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "openAiApi"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        },
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "169321ed-6956-4fb7-8519-038878488530",
      "name": "OpenAI \u2013 Extract Best Deal1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -464,
        4352
      ],
      "parameters": {
        "url": "https://api.openai.com/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"gpt-4o-mini\",\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"Analyze the shopping search results. Identify the best deal (lowest price from a reputable store). Return a JSON object with: 'bestDeal' (object with storeName, price, originalPrice, savingPct, url, currency), 'alternatives' (array of up to 2 other stores/prices), 'confidence' (high/low), and 'summary' (brief explanation).\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"={{ JSON.stringify($json.shopping) }}\"\n    }\n  ],\n  \"response_format\": { \"type\": \"json_object\" },\n  \"temperature\": 0\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "openAiApi"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        },
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "af99be87-074e-45e2-a491-b0bb268e0478",
      "name": "Process Deal Result1",
      "type": "n8n-nodes-base.code",
      "position": [
        -240,
        4352
      ],
      "parameters": {
        "jsCode": "// Parse deal, build item card, prepare Sheets row\nconst raw = $json?.choices?.[0]?.message?.content || '{}';\nlet d = {};\ntry { d = JSON.parse(raw); } catch(e) { const m = raw.match(/\\{[\\s\\S]*\\}/); if(m){try{d=JSON.parse(m[0]);}catch(e2){}} }\n\nconst src  = $('Prepare Search Queries1').item.json;\nconst best = d.bestDeal   || {};\nconst alts = d.alternatives || [];\nconst now  = new Date();\n\nconst saveBadge = (best.savingPct||0) > 0 ? ` \ud83c\udff7\ufe0f -${best.savingPct}%` : '';\nconst altLines  = alts.slice(0,2).map(a => `    \u2022 ${a.storeName}: \u20b9${a.price}`).join('\\n');\n\nconst itemCard = [\n  `\\n\ud83d\uded2 *${src.item}* (${src.qty} ${src.unit})`,\n  `  \u2705 *${best.storeName||'Unknown'}* \u2014 \u20b9${best.price||'N/A'}${saveBadge}`,\n  altLines ? `  Others:\\n${altLines}` : '',\n  best.url ? `  \ud83d\udd17 ${best.url}` : ''\n].filter(Boolean).join('\\n');\n\nreturn [{ json: {\n  listId:        src.listId,\n  phone:         src.phone,\n  userName:      src.userName,\n  item:          src.item,\n  qty:           src.qty,\n  unit:          src.unit,\n  storeName:     best.storeName     || 'Unknown',\n  price:         best.price         || 0,\n  originalPrice: best.originalPrice || best.price || 0,\n  savingPct:     best.savingPct     || 0,\n  currency:      best.currency      || 'INR',\n  url:           best.url           || '',\n  summary:       d.summary          || '',\n  confidence:    d.confidence        || 'low',\n  alternatives:  JSON.stringify(alts),\n  foundAt:       now.toISOString(),\n  alertSent:     'No',\n  itemCard\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "c2e8e927-2812-45e5-a71d-40b934f38b84",
      "name": "Google Sheets \u2013 Save Deals1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        16,
        4352
      ],
      "parameters": {
        "columns": {
          "value": {
            "url": "={{ $json.url }}",
            "item": "={{ $node['Google Sheets \u2013 Read List for Compare1'].json.item }}",
            "phone": "={{ $node['Google Sheets \u2013 Read List for Compare1'].json.phone }}",
            "price": "={{ $json.price }}",
            "listid": "={{ $node[\"Google Sheets \u2013 Read List for Compare1\"].json.listid }}",
            "foundAt": "={{ $json.foundAt }}",
            "summary": "={{ $json.summary }}",
            "Currency": "={{ $json.currency }}",
            "alertSent": "={{ $json.alertSent }}",
            "savingPct": "={{ $json.savingPct }}",
            "storeName": "={{ $json.storeName }}",
            "confidence": "={{ $json.confidence }}",
            "alternatives": "={{ $json.alternatives }}",
            "originalPrice": "={{ $json.originalPrice }}"
          },
          "schema": [
            {
              "id": "listid",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "listid",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "item",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "item",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "storeName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "storeName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "originalPrice",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "originalPrice",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "savingPct",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "savingPct",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Currency",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Currency",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "confidence",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "confidence",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "alternatives",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "alternatives",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "foundAt",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "foundAt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "alertSent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "alertSent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1354101119,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit#gid=1354101119",
          "cachedResultName": "Deals"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nLiq8cy7O-qfdDLtpzzAmDNDhIpR4-HCLS6c-y8v5-0/edit?usp=drivesdk",
          "cachedResultName": "Untitled spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "580a8a1e-2d20-4b59-8d66-26fa883c3251",
      "name": "Aggregate Comparison Card1",
      "type": "n8n-nodes-base.code",
      "position": [
        256,
        4352
      ],
      "parameters": {
        "jsCode": "// Aggregate all processed deal items into one comparison card\nconst all = $input.all();\nif (!all || all.length === 0) return [{ json: { phone:'', card:'No deals found.' } }];\n\nconst phone    = all[0].json.phone;\nconst userName = all[0].json.userName;\nconst now      = new Date();\n\nlet totalBest = 0, totalOrig = 0;\nconst cards = all.map(r => { totalBest += parseFloat(r.json.price||0); totalOrig += parseFloat(r.json.originalPrice||r.json.price||0); return r.json.itemCard; }).join('\\n');\n\nconst saved   = totalOrig - totalBest;\nconst savePct = totalOrig > 0 ? Math.round((saved / totalOrig) * 100) : 0;\nconst hiConf  = all.filter(r => r.json.confidence === 'high').length;\n\nconst lines = [\n  `\ud83d\udd0d *Price Comparison Report*`,\n  `\ud83d\udc64 ${userName} \u00b7 ${now.toLocaleDateString('en-IN',{day:'numeric',month:'short'})}`,\n  cards,\n  '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501',\n  `\ud83d\udcb0 *Estimated Total: \u20b9${totalBest.toFixed(0)}*`,\n  saved > 0 ? `\ud83c\udff7\ufe0f *You could save: \u20b9${saved.toFixed(0)} (${savePct}%)*` : '',\n  `\u2139\ufe0f ${hiConf}/${all.length} prices high-confidence`,\n  '',\n  'Prices are live estimates \u2014 verify before purchase.',\n  'Send *deals* anytime to review saved deals.'\n].filter(l => l !== '').join('\\n');\n\nreturn [{ json: { phone, card: lines } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "fa355182-765f-4690-8290-fcce9a7f4750",
      "name": "Schedule Trigger \u2013 Daily 8AM Alerts1",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1280,
        4672
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "0b0341cf-7ad4-4cbf-88fa-ecc9095bddde",
      "name": "Google Sheets \u2013 Read Deals for Alert1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1520,
        4672
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Deals"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "10b9c976-1234-4533-aad3-e7f959280019",
      "name": "Build Alert Messages1",
      "type": "n8n-nodes-base.code",
      "position": [
        1760,
        4672
      ],
      "parameters": {
        "jsCode": "// Build personalised daily deal alerts\nconst allRows = $input.all();\n\nconst alertable = allRows.filter(r => r.json.alertSent === 'No' && parseFloat(r.json.savingPct||0) >= 10);\nif (alertable.length === 0) return [{ json: { message: 'No deals to alert today', count: 0 } }];\n\nconst byPhone = {};\nfor (const r of alertable) {\n  const p = r.json.phone;\n  if (!byPhone[p]) byPhone[p] = { phone: p, userName: r.json.userName, deals: [] };\n  byPhone[p].deals.push(r.json);\n}\n\nreturn Object.values(byPhone).map(user => {\n  const top = user.deals.sort((a,b)=>parseFloat(b.savingPct)-parseFloat(a.savingPct)).slice(0,5);\n  const lines = [\n    `\ud83d\udd25 *Daily Deal Alert!*`,\n    `\ud83d\udc4b Hi *${user.userName}!* Best prices found for your list:`,\n    ''\n  ];\n  for (const d of top) {\n    lines.push(`\ud83d\uded2 *${d.item}* \u2014 \u20b9${d.price} at *${d.storeName}*`);\n    lines.push(`   \ud83c\udff7\ufe0f Save ${d.savingPct}% vs original price`);\n    if (d.url) lines.push(`   \ud83d\udd17 ${d.url}`);\n    lines.push('');\n  }\n  lines.push('\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501');\n  lines.push('Send *compare* to refresh prices anytime \ud83d\udd04');\n  return { json: { phone: user.phone, alertMessage: lines.join('\\n'), dealCount: top.length } };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "9698ad3b-7ab1-4675-8665-b6cc8fb755cf",
      "name": "Send a text message5",
      "type": "n8n-nodes-wati.wati",
      "onError": "continueRegularOutput",
      "position": [
        -528,
        3696
      ],
      "parameters": {
        "target": "={{ $('Wati Trigger').item.json.waId }}",
        "messageText": "={{ $('Structure List Items1').item.json.ackMessage }}"
      },
      "credentials": {
        "watiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8c745c6c-06f2-41ac-8362-bd7b444947e2",
      "name": "Send a text message6",
      "type": "n8n-nodes-wati.wati",
      "position": [
        464,
        4352
      ],
      "parameters": {
        "target": "={{ $node['Wati Trigger'].json.waId }}",
        "messageText": "={{ $json.card }}"
      },
      "credentials": {
        "watiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b55e03ed-b5bb-4aa2-88b9-3305323a86e3",
      "name": "Send a text message7",
      "type": "n8n-nodes-wati.wati",
      "position": [
        -656,
        4704
      ],
      "parameters": {
        "target": "={{ $node['Wati Trigger'].json.waId }}",
        "messageText": "={{ $json.msg }}"
      },
      "credentials": {
        "watiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "bba952b7-599a-478c-8f1e-b47f3f6f0541",
      "name": "Send a text message8",
      "type": "n8n-nodes-wati.wati",
      "position": [
        -576,
        5104
      ],
      "parameters": {
        "target": "={{ $('Wati Trigger').item.json.waId }}",
        "messageText": "={{ $json.msg }}"
      },
      "credentials": {
        "watiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e5422e68-f0a6-4a59-affb-b50814add91c",
      "name": "Send a text message9",
      "type": "n8n-nodes-wati.wati",
      "position": [
        -832,
        5504
      ],
      "parameters": {
        "target": "={{ $json.phone }}",
        "messageText": "={{ $json.msg }}"
      },
      "credentials": {
        "watiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5eb4b0e0-5bf2-46e7-b64e-8d764b6b3dd2",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1248,
        3552
      ],
      "parameters": {
        "color": 7,
        "width": 1136,
        "height": 384,
        "content": "**New List path:**\n`OpenAI \u2013 Parse List` \u2192 `Structure List Items` (generates one row per item + ackMessage) \u2192 `Google Sheets \u2013 Save Shopping List` \u2192 `Send a text message` (confirm to user)"
      },
      "typeVersion": 1
    },
    {
      "id": "0216abdb-cd4d-4b44-8b3c-e9b6047c0296",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1264,
        5376
      ],
      "parameters": {
        "color": 7,
        "width": 1040,
        "height": 272,
        "content": "\nSticky Note Title: \ud83e\uddf9 MAINTENANCE\nFunction: Handles the \"Clear\" intent.\nNote: This node currently prepares the \"Success\" message.\nTip: Ensure you have a Google Sheets node following this (or a specific script) if you want to physically delete rows or update status to 'inactive' in your database."
      },
      "typeVersion": 1
    },
    {
      "id": "bb3d20d1-6036-47d5-9fcb-031850a92415",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1280,
        4992
      ],
      "parameters": {
        "color": 7,
        "width": 1056,
        "height": 320,
        "content": "Sticky Note Title: \ud83d\udcb0 SAVINGS TRACKER\nFunction: Fetches the latest price data from the Deals sheet. Key Features:* Sorts by date to show the most recent prices first.De-duplicates items so the user only sees the latest deal per product.Calculates and displays Saving % and store links."
      },
      "typeVersion": 1
    },
    {
      "id": "7368a5fa-05c3-4b23-b627-8b68aa4468cd",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1264,
        4576
      ],
      "parameters": {
        "color": 7,
        "width": 928,
        "height": 320,
        "content": "Nodes: Google Sheets \u2013 Read My List1 & Build My List View1\n\nFunction: Pulls active shopping items from the ShoppingList sheet.Groups items by Category (Dairy, Produce, etc.).Adds specific emojis based on the category for a better mobile UI.Output: Formatted WhatsApp message with a summary and total count."
      },
      "typeVersion": 1
    },
    {
      "id": "00eea83e-1f55-40cd-8202-90793c3efa32",
      "name": "Wati Trigger",
      "type": "n8n-nodes-wati.watiTrigger",
      "position": [
        -1824,
        4320
      ],
      "parameters": {
        "event": "messageReceived"
      },
      "credentials": {
        "watiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "38f7f040-5864-4d76-b050-bb5325bdca4e",
      "name": "Send a text message",
      "type": "n8n-nodes-wati.wati",
      "position": [
        2048,
        4672
      ],
      "parameters": {
        "target": "78523",
        "messageText": "t"
      },
      "credentials": {
        "watiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Wati Trigger": {
      "main": [
        [
          {
            "node": "Intent Router1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Intent Router1": {
      "main": [
        [
          {
            "node": "OpenAI \u2013 Parse List1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets \u2013 Read List for Compare1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets \u2013 Read Saved Deals1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets \u2013 Read My List1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Process Clear1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Clear1": {
      "main": [
        [
          {
            "node": "Send a text message9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Deals View1": {
      "main": [
        [
          {
            "node": "Send a text message8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build My List View1": {
      "main": [
        [
          {
            "node": "Send a text message7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Deal Result1": {
      "main": [
        [
          {
            "node": "Google Sheets \u2013 Save Deals1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Alert Messages1": {
      "main": [
        [
          {
            "node": "Send a text message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structure List Items1": {
      "main": [
        [
          {
            "node": "Google Sheets \u2013 Save Shopping List1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI \u2013 Parse List1": {
      "main": [
        [
          {
            "node": "Structure List Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Search Queries1": {
      "main": [
        [
          {
            "node": "Serper \u2013 Search Prices1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Serper \u2013 Search Prices1": {
      "main": [
        [
          {
            "node": "OpenAI \u2013 Extract Best Deal1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Comparison Card1": {
      "main": [
        [
          {
            "node": "Send a text message6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Save Deals1": {
      "main": [
        [
          {
            "node": "Aggregate Comparison Card1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI \u2013 Extract Best Deal1": {
      "main": [
        [
          {
            "node": "Process Deal Result1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read My List1": {
      "main": [
        [
          {
            "node": "Build My List View1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read Saved Deals1": {
      "main": [
        [
          {
            "node": "Build Deals View1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Save Shopping List1": {
      "main": [
        [
          {
            "node": "Send a text message5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger \u2013 Daily 8AM Alerts1": {
      "main": [
        [
          {
            "node": "Google Sheets \u2013 Read Deals for Alert1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read Deals for Alert1": {
      "main": [
        [
          {
            "node": "Build Alert Messages1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2013 Read List for Compare1": {
      "main": [
        [
          {
            "node": "Prepare Search Queries1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}