{
  "id": "m3rGdoXJdGFTSnT6",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automate Hotel Price Comparison with Multi-Platform Scraping and Email Reporting",
  "tags": [],
  "nodes": [
    {
      "id": "fa0570b5-623e-4c19-b6de-f47b5e5fd9ac",
      "name": "Webhook - Receive Request",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -944,
        -128
      ],
      "parameters": {
        "path": "hotel-price-check",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 1.1
    },
    {
      "id": "cdac9db5-4b10-45e6-940f-4a98ecbe8c4a",
      "name": "Parse & Validate Request",
      "type": "n8n-nodes-base.code",
      "position": [
        -720,
        -128
      ],
      "parameters": {
        "jsCode": "// Enhanced NLP Parser for Hotel Requests\nconst input = $input.first().json.body;\nconst query = input.message || input.query || input.text || '';\nconst userEmail = input.email || input.user_email || '';\nconst userName = input.name || input.user_name || 'Guest';\n\n// Greeting handler\nconst greetings = ['hi', 'hello', 'hey', 'start', 'help'];\nif (greetings.some(g => query.toLowerCase().includes(g)) && query.split(' ').length < 5) {\n  return [{\n    json: {\n      status: 'greeting',\n      response: `Hi ${userName}! \ud83d\udc4b I'm your Hotel Price Assistant.\\n\\nJust tell me:\\n\u2705 Hotel name\\n\u2705 City\\n\u2705 Check-in & check-out dates\\n\\nExample: \"Hilton Hotel in Singapore from 15th March to 18th March\"`,\n      userEmail,\n      userName\n    }\n  }];\n}\n\n// Date parsing with multiple formats\nfunction parseDate(text) {\n  const monthMap = {\n    jan: 0, january: 0, feb: 1, february: 1, mar: 2, march: 2,\n    apr: 3, april: 3, may: 4, jun: 5, june: 5,\n    jul: 6, july: 6, aug: 7, august: 7, sep: 8, september: 8,\n    oct: 9, october: 9, nov: 10, november: 10, dec: 11, december: 11\n  };\n\n  // Format: \"15th March\" or \"March 15\"\n  const dateRegex = /(\\d{1,2})(st|nd|rd|th)?\\s+(jan|january|feb|february|mar|march|apr|april|may|jun|june|jul|july|aug|august|sep|september|oct|october|nov|november|dec|december)|(jan|january|feb|february|mar|march|apr|april|may|jun|june|jul|july|aug|august|sep|september|oct|october|nov|november|dec|december)\\s+(\\d{1,2})(st|nd|rd|th)?/gi;\n  \n  const matches = [...text.matchAll(dateRegex)];\n  const dates = [];\n  const currentYear = new Date().getFullYear();\n  \n  matches.forEach(match => {\n    const day = parseInt(match[1] || match[6]);\n    const monthStr = (match[3] || match[4]).toLowerCase();\n    const month = monthMap[monthStr];\n    \n    if (day && month !== undefined) {\n      dates.push(new Date(currentYear, month, day));\n    }\n  });\n  \n  return dates.sort((a, b) => a - b);\n}\n\nconst dates = parseDate(query);\nlet checkInDate = null;\nlet checkOutDate = null;\n\nif (dates.length >= 2) {\n  checkInDate = dates[0];\n  checkOutDate = dates[1];\n} else if (dates.length === 1) {\n  checkInDate = dates[0];\n  // Default 3-night stay\n  checkOutDate = new Date(checkInDate);\n  checkOutDate.setDate(checkOutDate.getDate() + 3);\n}\n\n// Extract city\nconst cityPattern = /\\b(in|at|near)\\s+([a-z\\s]{3,20})(?=\\s+from|\\s+check|,|$)/i;\nconst cityMatch = query.match(cityPattern);\nlet city = cityMatch ? cityMatch[2].trim() : '';\n\n// Common cities fallback\nconst commonCities = ['singapore', 'mumbai', 'delhi', 'bangalore', 'goa', 'london', 'paris', 'dubai', 'new york', 'tokyo', 'bangkok'];\ncity = city || commonCities.find(c => query.toLowerCase().includes(c)) || '';\n\n// Extract hotel name\nlet hotelName = query\n  .replace(/from\\s+\\d/gi, '')\n  .replace(/to\\s+\\d/gi, '')\n  .replace(/check[- ]?in/gi, '')\n  .replace(/check[- ]?out/gi, '')\n  .replace(/\\d{1,2}(st|nd|rd|th)?\\s+\\w+/gi, '')\n  .replace(new RegExp(`\\\\b(in|at|near)\\\\s+${city}\\\\b`, 'gi'), '')\n  .replace(/hotel|room|price|want|need|know|please|for|dates?/gi, '')\n  .trim();\n\n// Clean hotel name\nhotelName = hotelName.split(/[,.]/).filter(p => p.trim().length > 2)[0]?.trim() || '';\n\n// Validation\nconst errors = [];\nif (!hotelName || hotelName.length < 3) errors.push('hotel name');\nif (!city) errors.push('city');\nif (!checkInDate) errors.push('check-in date');\nif (!checkOutDate) errors.push('check-out date');\n\nif (errors.length > 0) {\n  return [{\n    json: {\n      status: 'missing_info',\n      response: `I need more information. Please provide: ${errors.join(', ')}.\\n\\nExample: \"Marriott Hotel in Dubai from 20th December to 23rd December\"`,\n      userEmail,\n      userName\n    }\n  }];\n}\n\n// Format dates\nconst formatDate = (date) => {\n  const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\n  return `${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}`;\n};\n\nconst nights = Math.ceil((checkOutDate - checkInDate) / (1000 * 60 * 60 * 24));\n\nreturn [{\n  json: {\n    status: 'ready',\n    hotelName: hotelName.split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(' '),\n    city: city.split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(' '),\n    checkIn: formatDate(checkInDate),\n    checkOut: formatDate(checkOutDate),\n    checkInISO: checkInDate.toISOString().split('T')[0],\n    checkOutISO: checkOutDate.toISOString().split('T')[0],\n    nights,\n    userEmail,\n    userName,\n    originalQuery: query\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e6bc8693-f361-4e71-bc5b-3fee26331176",
      "name": "Check If Ready",
      "type": "n8n-nodes-base.if",
      "position": [
        -496,
        -128
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json.status}}",
              "value2": "ready"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3bfffcf2-29fc-4a34-9aef-d88bebc1291f",
      "name": "Scrape Booking.com",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -272,
        -416
      ],
      "parameters": {
        "url": "https://api.example.com/scrape/booking",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "hotel",
              "value": "={{$json.hotelName}}"
            },
            {
              "name": "city",
              "value": "={{$json.city}}"
            },
            {
              "name": "checkIn",
              "value": "={{$json.checkInISO}}"
            },
            {
              "name": "checkOut",
              "value": "={{$json.checkOutISO}}"
            },
            {
              "name": "platform",
              "value": "booking"
            }
          ]
        }
      },
      "typeVersion": 4.1,
      "continueOnFail": true
    },
    {
      "id": "1fbf0962-d1e2-4b18-9b5f-8ddbbbec6060",
      "name": "Scrape Agoda",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -272,
        -224
      ],
      "parameters": {
        "url": "https://api.example.com/scrape/agoda",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "hotel",
              "value": "={{$json.hotelName}}"
            },
            {
              "name": "city",
              "value": "={{$json.city}}"
            },
            {
              "name": "checkIn",
              "value": "={{$json.checkInISO}}"
            },
            {
              "name": "checkOut",
              "value": "={{$json.checkOutISO}}"
            },
            {
              "name": "platform",
              "value": "agoda"
            }
          ]
        }
      },
      "typeVersion": 4.1,
      "continueOnFail": true
    },
    {
      "id": "9044675b-7dbd-43b1-9dd7-2adc3f176d48",
      "name": "Scrape Expedia",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -272,
        -32
      ],
      "parameters": {
        "url": "https://api.example.com/scrape/expedia",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "hotel",
              "value": "={{$json.hotelName}}"
            },
            {
              "name": "city",
              "value": "={{$json.city}}"
            },
            {
              "name": "checkIn",
              "value": "={{$json.checkInISO}}"
            },
            {
              "name": "checkOut",
              "value": "={{$json.checkOutISO}}"
            },
            {
              "name": "platform",
              "value": "expedia"
            }
          ]
        }
      },
      "typeVersion": 4.1,
      "continueOnFail": true
    },
    {
      "id": "401b0e56-d028-4345-8b4a-0920e6a678f5",
      "name": "Aggregate & Compare",
      "type": "n8n-nodes-base.code",
      "position": [
        -48,
        -224
      ],
      "parameters": {
        "jsCode": "// Aggregate and compare prices from all platforms\nconst items = $input.all();\nconst searchData = items[0].json;\n\nconst prices = [];\nconst errors = [];\n\n// Process each platform result\nitems.slice(1).forEach((item, index) => {\n  const platforms = ['Booking.com', 'Agoda', 'Expedia'];\n  const platform = platforms[index];\n  \n  if (item.json.error) {\n    errors.push(`${platform}: Unable to fetch`);\n  } else if (item.json.price) {\n    prices.push({\n      platform,\n      price: parseFloat(item.json.price),\n      currency: item.json.currency || 'USD',\n      roomType: item.json.roomType || 'Standard Room',\n      url: item.json.url || '#',\n      availability: item.json.availability !== false\n    });\n  }\n});\n\n// Sort by price\nprices.sort((a, b) => a.price - b.price);\n\nif (prices.length === 0) {\n  return [{\n    json: {\n      status: 'no_results',\n      message: 'Unable to find prices. The hotel might not be available for these dates.',\n      errors,\n      ...searchData\n    }\n  }];\n}\n\nconst bestDeal = prices[0];\nconst avgPrice = prices.reduce((sum, p) => sum + p.price, 0) / prices.length;\nconst savings = prices.length > 1 ? prices[prices.length - 1].price - bestDeal.price : 0;\n\nreturn [{\n  json: {\n    status: 'success',\n    ...searchData,\n    results: prices,\n    bestDeal,\n    avgPrice: Math.round(avgPrice),\n    savings: Math.round(savings),\n    totalResults: prices.length,\n    errors\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "0e569c2e-fd37-4bf8-a80e-385dd6580b10",
      "name": "Format Email Report",
      "type": "n8n-nodes-base.code",
      "position": [
        176,
        -224
      ],
      "parameters": {
        "jsCode": "// Format beautiful email with comparison\nconst data = $input.first().json;\n\nif (data.status === 'no_results') {\n  return [{\n    json: {\n      subject: `\u274c No Results - ${data.hotelName}, ${data.city}`,\n      html: `\n        <div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n          <h2>\u274c Unable to Find Prices</h2>\n          <p>We couldn't find available prices for:</p>\n          <div style=\"background: #f5f5f5; padding: 15px; border-radius: 8px;\">\n            <strong>${data.hotelName}</strong><br>\n            \ud83d\udccd ${data.city}<br>\n            \ud83d\udcc5 ${data.checkIn} to ${data.checkOut} (${data.nights} nights)\n          </div>\n          <p style=\"margin-top: 20px;\">Possible reasons:</p>\n          <ul>\n            <li>Hotel not available on these dates</li>\n            <li>Hotel name might be different on booking platforms</li>\n            <li>No rooms available</li>\n          </ul>\n          <p>Please try:</p>\n          <ul>\n            <li>Different dates</li>\n            <li>Checking the exact hotel name</li>\n            <li>Another hotel in ${data.city}</li>\n          </ul>\n        </div>\n      `,\n      ...data\n    }\n  }];\n}\n\nconst { hotelName, city, checkIn, checkOut, nights, results, bestDeal, avgPrice, savings } = data;\n\nconst resultsHtml = results.map((r, i) => `\n  <tr style=\"${i === 0 ? 'background: #e8f5e9;' : ''}\">\n    <td style=\"padding: 12px; border-bottom: 1px solid #ddd;\">\n      ${i === 0 ? '\ud83c\udfc6 ' : ''}<strong>${r.platform}</strong>\n    </td>\n    <td style=\"padding: 12px; border-bottom: 1px solid #ddd;\">${r.roomType}</td>\n    <td style=\"padding: 12px; border-bottom: 1px solid #ddd; text-align: right;\">\n      <strong style=\"color: ${i === 0 ? '#2e7d32' : '#333'}; font-size: 18px;\">\n        ${r.currency} ${r.price.toLocaleString()}\n      </strong>\n    </td>\n    <td style=\"padding: 12px; border-bottom: 1px solid #ddd; text-align: center;\">\n      <a href=\"${r.url}\" style=\"background: #1976d2; color: white; padding: 8px 16px; text-decoration: none; border-radius: 4px; display: inline-block;\">View</a>\n    </td>\n  </tr>\n`).join('');\n\nconst html = `\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n</head>\n<body style=\"margin: 0; padding: 20px; background: #f5f5f5; font-family: Arial, sans-serif;\">\n  <div style=\"max-width: 650px; margin: 0 auto; background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);\">\n    \n    <!-- Header -->\n    <div style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center;\">\n      <h1 style=\"margin: 0; font-size: 28px;\">\ud83c\udfe8 Hotel Price Comparison</h1>\n      <p style=\"margin: 10px 0 0 0; opacity: 0.9;\">Best deals for your stay</p>\n    </div>\n\n    <!-- Hotel Info -->\n    <div style=\"padding: 25px; background: #f8f9fa;\">\n      <h2 style=\"margin: 0 0 15px 0; color: #333;\">${hotelName}</h2>\n      <div style=\"color: #666; line-height: 1.8;\">\n        <div>\ud83d\udccd <strong>Location:</strong> ${city}</div>\n        <div>\ud83d\udcc5 <strong>Check-in:</strong> ${checkIn}</div>\n        <div>\ud83d\udcc5 <strong>Check-out:</strong> ${checkOut}</div>\n        <div>\ud83c\udf19 <strong>Duration:</strong> ${nights} night${nights > 1 ? 's' : ''}</div>\n      </div>\n    </div>\n\n    <!-- Best Deal Highlight -->\n    <div style=\"margin: 20px; padding: 20px; background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%); border-radius: 8px; border-left: 4px solid #667eea;\">\n      <div style=\"font-size: 14px; color: #667eea; font-weight: bold; margin-bottom: 8px;\">\ud83c\udfc6 BEST DEAL FOUND</div>\n      <div style=\"font-size: 24px; font-weight: bold; color: #333; margin-bottom: 5px;\">\n        ${bestDeal.currency} ${bestDeal.price.toLocaleString()}\n      </div>\n      <div style=\"color: #666;\">on ${bestDeal.platform} \u2022 ${bestDeal.roomType}</div>\n      ${savings > 0 ? `<div style=\"margin-top: 10px; color: #2e7d32; font-weight: bold;\">\ud83d\udcb0 Save ${bestDeal.currency} ${savings.toLocaleString()} compared to highest price!</div>` : ''}\n    </div>\n\n    <!-- Price Comparison Table -->\n    <div style=\"padding: 0 20px 20px 20px;\">\n      <h3 style=\"color: #333; margin-bottom: 15px;\">\ud83d\udcca Price Comparison</h3>\n      <table style=\"width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);\">\n        <thead>\n          <tr style=\"background: #f5f5f5;\">\n            <th style=\"padding: 12px; text-align: left; color: #666; font-weight: 600;\">Platform</th>\n            <th style=\"padding: 12px; text-align: left; color: #666; font-weight: 600;\">Room Type</th>\n            <th style=\"padding: 12px; text-align: right; color: #666; font-weight: 600;\">Price</th>\n            <th style=\"padding: 12px; text-align: center; color: #666; font-weight: 600;\">Action</th>\n          </tr>\n        </thead>\n        <tbody>\n          ${resultsHtml}\n        </tbody>\n      </table>\n      \n      <div style=\"margin-top: 15px; padding: 15px; background: #f8f9fa; border-radius: 8px; text-align: center; color: #666;\">\n        <strong>Average Price:</strong> ${bestDeal.currency} ${avgPrice.toLocaleString()}\n      </div>\n    </div>\n\n    <!-- Footer -->\n    <div style=\"padding: 20px; background: #f8f9fa; border-top: 1px solid #e0e0e0; text-align: center; color: #666; font-size: 13px;\">\n      <p style=\"margin: 0 0 10px 0;\">\u2728 Prices are subject to availability and may change.</p>\n      <p style=\"margin: 0;\">Happy travels! \ud83c\udf0d</p>\n    </div>\n\n  </div>\n</body>\n</html>\n`;\n\nreturn [{\n  json: {\n    subject: `\ud83c\udfe8 ${hotelName} - Best Price: ${bestDeal.currency} ${bestDeal.price.toLocaleString()}`,\n    html,\n    ...data\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f1d4a0a7-0441-4609-8e35-0db86378de93",
      "name": "Send Email Report",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        400,
        -320
      ],
      "parameters": {
        "options": {},
        "subject": "={{$json.subject}}",
        "toEmail": "={{$json.userEmail}}",
        "fromEmail": "user@example.com"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "3a3a94aa-23f4-4758-9fb7-bac33b35ecca",
      "name": "Webhook Response (Success)",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        624,
        -320
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ {\\n  \"success\": true,\\n  \"message\": \"Price comparison sent to your email!\",\\n  \"hotel\": $json.hotelName,\\n  \"bestPrice\": $json.bestDeal.price,\\n  \"platform\": $json.bestDeal.platform\\n} }}"
      },
      "typeVersion": 1
    },
    {
      "id": "1a4fd9f4-b08e-4c7e-9ab5-cc9c0e9cdf7f",
      "name": "Webhook Response (Info)",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        848,
        48
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ {\\n  \"success\": false,\\n  \"message\": $json.response,\\n  \"status\": $json.status\\n} }}"
      },
      "typeVersion": 1
    },
    {
      "id": "460b6b8d-679e-4876-9f45-b0b6aa432f8e",
      "name": "Log Analytics",
      "type": "n8n-nodes-base.set",
      "position": [
        400,
        -32
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{ {\\n  \"timestamp\": $now,\\n  \"query\": $json.originalQuery,\\n  \"hotel\": $json.hotelName,\\n  \"city\": $json.city,\\n  \"checkIn\": $json.checkIn,\\n  \"checkOut\": $json.checkOut,\\n  \"bestPrice\": $json.bestDeal?.price,\\n  \"platform\": $json.bestDeal?.platform,\\n  \"totalResults\": $json.totalResults,\\n  \"userEmail\": $json.userEmail\\n} }}"
      },
      "typeVersion": 3.2
    },
    {
      "id": "c7984244-c4d7-4343-88d6-422e1f54a06f",
      "name": "Save to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        624,
        -32
      ],
      "parameters": {
        "columns": {
          "mappingMode": "autoMapInputData"
        },
        "options": {},
        "operation": "append",
        "sheetName": "Analytics",
        "documentId": "your-google-sheet-id",
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "0de90b41-12aa-4997-96f9-ee90d6b59ebe",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -960,
        -304
      ],
      "parameters": {
        "width": 150,
        "height": 352,
        "content": "User sends natural language query"
      },
      "typeVersion": 1
    },
    {
      "id": "4cda970d-9585-43e2-b188-f7662e9ecee2",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -768,
        -304
      ],
      "parameters": {
        "color": 4,
        "width": 192,
        "height": 352,
        "content": "Extract hotel, city, dates"
      },
      "typeVersion": 1
    },
    {
      "id": "6ca495c6-d8bd-483d-a79a-8c4b4d8e58ef",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -528,
        -304
      ],
      "parameters": {
        "color": 3,
        "width": 150,
        "height": 352,
        "content": "Validate all required info"
      },
      "typeVersion": 1
    },
    {
      "id": "b120b69f-566c-4c91-af14-8ee7171d0288",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        -400
      ],
      "parameters": {
        "color": 5,
        "width": 150,
        "height": 352,
        "content": "Compare prices, find best deal"
      },
      "typeVersion": 1
    },
    {
      "id": "6835fed2-3bed-4591-85b3-7e0ea31c3ec0",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        -400
      ],
      "parameters": {
        "color": 3,
        "width": 150,
        "height": 352,
        "content": "Create beautiful HTML report"
      },
      "typeVersion": 1
    },
    {
      "id": "c661889d-6ab1-48ed-8044-f7616aa53999",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        -464
      ],
      "parameters": {
        "width": 662,
        "height": 656,
        "content": "Send response"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "7e3f322c-14e9-4659-a3eb-8265b957e295",
  "connections": {
    "Scrape Agoda": {
      "main": [
        [
          {
            "node": "Aggregate & Compare",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Analytics": {
      "main": [
        [
          {
            "node": "Save to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Ready": {
      "main": [
        [
          {
            "node": "Scrape Booking.com",
            "type": "main",
            "index": 0
          },
          {
            "node": "Scrape Agoda",
            "type": "main",
            "index": 0
          },
          {
            "node": "Scrape Expedia",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Webhook Response (Info)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Expedia": {
      "main": [
        [
          {
            "node": "Aggregate & Compare",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email Report": {
      "main": [
        [
          {
            "node": "Webhook Response (Success)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Booking.com": {
      "main": [
        [
          {
            "node": "Aggregate & Compare",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate & Compare": {
      "main": [
        [
          {
            "node": "Format Email Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Email Report": {
      "main": [
        [
          {
            "node": "Send Email Report",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Analytics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save to Google Sheets": {
      "main": [
        [
          {
            "node": "Webhook Response (Info)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse & Validate Request": {
      "main": [
        [
          {
            "node": "Check If Ready",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - Receive Request": {
      "main": [
        [
          {
            "node": "Parse & Validate Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}