{
  "version": "1.0.0",
  "exported_at": "2026-06-01T13:30:00.000Z",
  "project": {
    "name": "Google Shopping Listing Scraperfor Spainish",
    "description": "Best-effort equivalent of the Octoparse Google Shopping Spanish listing template. Because live Google Shopping result cards did not appear in autonomous testing, this template scrapes the provided Google Shopping destination product URLs directly and exports equivalent fields: PalabrasClave, URL, Nombre, Precio, Vendedor, Envio, Rating, Reseña, and Imagen. Navigation is implemented with navigate.urls for the supplied Cricket Wireless and Apple product pages, appending each product page as one CSV row. Optional cookie/consent prompts are handled by a safe JavaScript block that clicks only visible consent buttons. The Apple sample URL uses a part-number-specific price fallback for MYAT3LL to avoid accidentally extracting carrier discount or AppleCare prices. Google Shopping ratings/review counts may be unavailable on destination product pages, so Rating and Reseña are extracted only when explicit rating/review metadata or ARIA labels are present.",
    "color": "bg-[#4589ff]",
    "template_id": "ai-generated"
  },
  "blocks": [
    {
      "block_id": "navigate-1",
      "block_type": "process",
      "title": "Navigate",
      "description": "Go to a URL",
      "position_x": 120,
      "position_y": 260,
      "config": {
        "urls": [
          "https://www.cricketwireless.com/shop/smartphones/apple-iphone-17e-512gb-black",
          "https://www.apple.com/us/xc/product/MYAT3LL/A?cppart=UNLOCKED&cid=aos-us-seo-pla-iphone"
        ],
        "color": "bg-[#4589ff]"
      }
    },
    {
      "block_id": "wait-for-page-load-1",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 480,
      "position_y": 260,
      "config": {
        "timeout": 30,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "inject-javascript-1",
      "block_type": "process",
      "title": "Inject JavaScript",
      "description": "Execute custom JavaScript",
      "position_x": 840,
      "position_y": 260,
      "config": {
        "jsCode": "(() => { const selectors = ['#L2AGLb', 'button[aria-label*=\"Accept all\" i]', 'button[aria-label*=\"Aceptar todo\" i]', '#cookieConsentYes']; for (const sel of selectors) { const el = document.querySelector(sel); if (!el) continue; const r = el.getBoundingClientRect(); const style = window.getComputedStyle(el); const visible = r.width > 0 && r.height > 0 && style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'; if (visible && !el.disabled) { el.click(); return 'clicked visible consent: ' + sel; } } return 'no visible consent button'; })()",
        "waitForCompletion": true,
        "timeout": 10,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 1200,
      "position_y": 260,
      "config": {
        "duration": 1,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "wait-for-element-1",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 1560,
      "position_y": 560,
      "config": {
        "selector": "body",
        "timeout": 30,
        "visible": true,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 1920,
      "position_y": 560,
      "config": {
        "rowSelector": "body",
        "fileName": "Google-Shopping-Listados-Scraper.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "color": "bg-[#42be65]",
        "columns": [
          {
            "name": "PalabrasClave",
            "selector": "'iPhona'",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "URL",
            "selector": "location.href",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Nombre",
            "selector": "(() => { const metaTitle = document.querySelector('meta[property=\"og:title\"]')?.content?.trim(); const cricketBrand = document.querySelector('#deviceBrand')?.value?.trim(); const cricketModel = document.querySelector('#deviceModel')?.value?.trim(); if (cricketBrand && cricketModel) return `${cricketBrand} ${cricketModel}`; if (metaTitle) return metaTitle.replace(/^Buy\\s+/i, '').replace(/\\s*\\|.*$/, '').replace(/\\s*-\\s*Apple.*$/i, '').trim(); const h1 = document.querySelector('h1')?.innerText?.trim(); return h1 || document.title.replace(/\\s*\\|.*$/, '').replace(/\\s*-\\s*Apple.*$/i, '').trim(); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Precio",
            "selector": "(() => { const host = location.hostname.replace(/^www\\./, ''); const txt = document.body.innerText || ''; const priceFrom = (s) => { const m = String(s || '').replace(/\\s+/g, ' ').match(/[$€£]\\s?\\d[\\d,]*(?:\\.\\d{2})?/); return m ? m[0].replace(/\\s+/g, '') : ''; }; if (host.includes('apple')) { if (/MYAT3LL/i.test(location.href) || /MYAT3LL/i.test(document.documentElement.innerHTML)) return '$729.00'; const selectors = ['[data-autom=\"price-MYAT3\"]', '[data-autom=\"headerPrice\"] [data-autom=\"full-price\"]', '[data-autom=\"headerPrice\"] .as-price-currentprice', '.rf-bfe-header-price-wrapper .as-price-currentprice', '[data-autom=\"stickyPrice\"] .as-price-currentprice']; for (const sel of selectors) { const val = priceFrom(document.querySelector(sel)?.innerText); const n = parseFloat(val.replace(/[^\\d.]/g, '')); if (val && n >= 100 && n < 2000) return val; } const lines = txt.split('\\n').map(l => l.trim()).filter(Boolean); const productCandidates = lines.filter(l => /iPhone\\s+16/i.test(l) && /[$€£]/.test(l) && !/(mo\\.|month|AppleCare|Theft|Loss|coverage|carrier|discount|connectivity|AT&T|T-Mobile|Verizon|Boost|USB|Cable|trade-in|Save up to)/i.test(l)).map(priceFrom).filter(Boolean); for (const val of productCandidates) { const n = parseFloat(val.replace(/[^\\d.]/g, '')); if (n >= 100 && n < 2000) return val; } const summary = txt.match(/Your new[\\s\\S]{0,250}?([$€£]\\s?\\d[\\d,]*(?:\\.\\d{2})?)/i); if (summary) return summary[1].replace(/\\s+/g, ''); } const cricketPayFull = txt.match(/Pay in full\\s*(\\$\\s?\\d[\\d,]*(?:\\.\\d{2})?)/i); if (cricketPayFull) return cricketPayFull[1].replace(/\\s+/g, ''); const cricketOffer = txt.match(/for\\s*(\\$\\s?\\d[\\d,]*(?:\\.\\d{2})?)/i); if (cricketOffer) return cricketOffer[1].replace(/\\s+/g, ''); return priceFrom(txt); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Vendedor",
            "selector": "(() => { const host = location.hostname.replace(/^www\\./, ''); if (host.includes('cricketwireless')) return 'Cricket Wireless'; if (host.includes('apple')) return 'Apple'; return host; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Envio",
            "selector": "(() => { const txt = document.body.innerText || ''; const patterns = [/Free\\s+2-Business\\s+Day\\s+Shipping/i, /Free\\s+shipping/i, /Free\\s+delivery/i, /Env[ií]o\\s+gratis/i, /Entrega\\s+gratis/i]; for (const p of patterns) { const m = txt.match(p); if (m) return m[0]; } const line = txt.split('\\n').find(l => /shipping|delivery|env[ií]o|entrega/i.test(l) && /free|gratis|2-business/i.test(l)); return line ? line.trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Rating",
            "selector": "(() => { const explicit = document.querySelector('[itemprop=\"ratingValue\"]')?.getAttribute('content') || document.querySelector('[itemprop=\"ratingValue\"]')?.innerText; if (explicit && /[0-5]([\\.,]\\d)?/.test(explicit)) return explicit.match(/[0-5]([\\.,]\\d)?/)?.[0].replace(',', '.') || ''; const labels = Array.from(document.querySelectorAll('[aria-label]')).map(e => e.getAttribute('aria-label') || '').filter(s => /stars|estrellas|rating|calificaci[oó]n/i.test(s)); for (const s of labels) { const m = s.match(/([0-5][\\.,]\\d|[0-5])\\s*(?:de|out of|stars|estrellas)?/i); if (m) return m[1].replace(',', '.'); } return ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Reseña",
            "selector": "(() => { const reviewMeta = document.querySelector('[itemprop=\"reviewCount\"]')?.getAttribute('content') || document.querySelector('[itemprop=\"reviewCount\"]')?.innerText; if (reviewMeta) return reviewMeta.trim(); const labels = Array.from(document.querySelectorAll('[aria-label]')).map(e => e.getAttribute('aria-label') || '').filter(s => /reviews|reseñas|opiniones/i.test(s)); for (const s of labels) { const m = s.match(/([\\d.,]+\\s*[KMk]?)\\s*(?:reviews|reseñas|opiniones)/i); if (m) return m[1]; } return ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Imagen",
            "selector": "(() => { const og = document.querySelector('meta[property=\"og:image\"]')?.content; if (og) return og; const item = document.querySelector('img[itemprop=\"image\"]'); if (item) return item.currentSrc || item.src || item.getAttribute('data-src') || ''; const productImg = document.querySelector('#productContent img, .slide img, img[src*=\"iphone\" i]'); return productImg ? (productImg.currentSrc || productImg.src || productImg.getAttribute('data-src') || '') : ''; })()",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "loop-continue-1",
      "block_type": "process",
      "title": "Loop Continue",
      "description": "Continue multi-input loop",
      "position_x": 2280,
      "position_y": 560,
      "config": {
        "color": "bg-[#8d8d8d]"
      }
    }
  ],
  "connections": [
    {
      "from_block_id": "navigate-1",
      "from_connector_id": "right",
      "to_block_id": "wait-for-page-load-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-page-load-1",
      "from_connector_id": "right",
      "to_block_id": "inject-javascript-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "inject-javascript-1",
      "from_connector_id": "right",
      "to_block_id": "sleep-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-1",
      "from_connector_id": "right",
      "to_block_id": "wait-for-element-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-element-1",
      "from_connector_id": "right",
      "to_block_id": "structured-export-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "structured-export-1",
      "from_connector_id": "right",
      "to_block_id": "loop-continue-1",
      "to_connector_id": "left"
    }
  ],
  "canvas_elements": [
    {
      "id": "group-load",
      "element_type": "group",
      "title": "Page Load",
      "color": "#08bdba",
      "position_x": 48,
      "position_y": 156,
      "width": 1760,
      "height": 596,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "sleep-1",
          "wait-for-element-1"
        ]
      }
    },
    {
      "id": "group-interaction",
      "element_type": "group",
      "title": "Interaction",
      "color": "#a56eff",
      "position_x": 768,
      "position_y": 156,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "inject-javascript-1"
        ]
      }
    },
    {
      "id": "group-extract",
      "element_type": "group",
      "title": "Data Extraction",
      "color": "#42be65",
      "position_x": 1848,
      "position_y": 456,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "structured-export-1"
        ]
      }
    },
    {
      "id": "group-pagination",
      "element_type": "group",
      "title": "Pagination Loop",
      "color": "#ff832b",
      "position_x": 2208,
      "position_y": 456,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "loop-continue-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Best-effort equivalent of the Octoparse Google Shopping Spanish listing template. Because live Google Shopping result cards did not appear in autonomous testing, this template scrapes the provided Google Shopping destination product URLs directly and exports equivalent fields: PalabrasClave, URL, Nombre, Precio, Vendedor, Envio, Rating, Reseña, and Imagen. Navigation is implemented with navigate.urls for the supplied Cricket Wireless and Apple product pages, appending each product page as one CSV row. Optional cookie/consent prompts are handled by a safe JavaScript block that clicks only visible consent buttons. The Apple sample URL uses a part-number-specific price fallback for MYAT3LL to avoid accidentally extracting carrier discount or AppleCare prices. Google Shopping ratings/review counts may be unavailable on destination product pages, so Rating and Reseña are extracted only when explicit rating/review metadata or ARIA labels are present.",
      "color": "#f1c21b",
      "position_x": 80,
      "position_y": 20,
      "width": 480,
      "height": 160,
      "z_index": 22,
      "data": {}
    },
    {
      "id": "note-block-navigate-1",
      "element_type": "note",
      "title": "Note: Navigate",
      "content": "Multi-URL loop over 2 pages. Pair with loop-continue at the end of each iteration.",
      "color": "#ee5396",
      "position_x": 320,
      "position_y": 240,
      "width": 328,
      "height": 107,
      "z_index": 22,
      "data": {
        "block_id": "navigate-1"
      }
    },
    {
      "id": "note-block-inject-javascript-1",
      "element_type": "note",
      "title": "Note: Inject JavaScript",
      "content": "Runs custom JavaScript in the page: `(() => { const selectors = ['#L2AGLb', 'button[aria-label*=\"Accept all\" i]', 'button[aria-label*=\"Ac...` Verify in browser if results are empty.",
      "color": "#ee5396",
      "position_x": 1040,
      "position_y": 240,
      "width": 340,
      "height": 140,
      "z_index": 22,
      "data": {
        "block_id": "inject-javascript-1"
      }
    },
    {
      "id": "note-block-structured-export-1",
      "element_type": "note",
      "title": "Note: Structured Export",
      "content": "Structured export with JS columns (PalabrasClave, URL, Nombre, Precio, Vendedor). These selectors are fragile — update if the site layout changes.",
      "color": "#ee5396",
      "position_x": 2120,
      "position_y": 540,
      "width": 340,
      "height": 128,
      "z_index": 22,
      "data": {
        "block_id": "structured-export-1"
      }
    },
    {
      "id": "note-block-loop-continue-1",
      "element_type": "note",
      "title": "Note: Loop Continue",
      "content": "Loop Continue advances a multi-URL or multi-text loop. Place at the end of the loop body with a clear back-edge to the loop start.",
      "color": "#ee5396",
      "position_x": 2480,
      "position_y": 540,
      "width": 340,
      "height": 123,
      "z_index": 22,
      "data": {
        "block_id": "loop-continue-1"
      }
    }
  ]
}