{
  "version": "1.0.0",
  "exported_at": "2026-06-03T00:00:00.000Z",
  "project": {
    "name": "Superpages Details Page Scraper Cloud",
    "description": "Best-effort UScraper equivalent of the Octoparse Superpages Details Page Scraper. Uses Superpages search for keyword=supermarket and location=95136, extracts Octoparse-like business lead fields from each result card, and clicks Next until no enabled next page is found. Output is appended across pages. Edit the Navigate URL and keyword/location JS constants for other inputs. Some detail-only fields may be empty if not present on listing cards.",
    "color": "bg-[#4589ff]",
    "template_id": "ai-generated"
  },
  "blocks": [
    {
      "block_id": "set-window-size-1",
      "block_type": "process",
      "title": "Set Window Size",
      "description": "Set browser viewport size",
      "position_x": 120,
      "position_y": 280,
      "config": {
        "width": 1920,
        "height": 1080,
        "color": "bg-[#4589ff]"
      }
    },
    {
      "block_id": "navigate-1",
      "block_type": "process",
      "title": "Navigate",
      "description": "Go to a URL",
      "position_x": 480,
      "position_y": 280,
      "config": {
        "url": "https://www.superpages.com/search?search_terms=supermarket&geo_location_terms=95136",
        "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": 840,
      "position_y": 280,
      "config": {
        "timeout": 30,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "wait-for-element-1",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 1200,
      "position_y": 280,
      "config": {
        "selector": ".search-results .result, .organic .result, div.result, article.result",
        "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": 1560,
      "position_y": 280,
      "config": {
        "rowSelector": ".search-results .result, .organic .result, div.result, article.result",
        "fileName": "superpages-listing-scraper.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "color": "bg-[#42be65]",
        "columns": [
          {
            "name": "keyword",
            "selector": "'supermarket'",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "location",
            "selector": "'95136'",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "detail_url",
            "selector": "(() => { const a = ROW.querySelector('a.business-name, h2 a[href*=\"/bpp/\"], h3 a[href*=\"/bpp/\"], a[href*=\"/bpp/\"]'); return a ? a.href : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "business_name",
            "selector": "(() => { const el = ROW.querySelector('.business-name, h2, h3, [itemprop=\"name\"]'); return el ? el.textContent.replace(/Add to Favorites/gi, '').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "address",
            "selector": "(() => { const el = ROW.querySelector('.adr, .address, [itemprop=\"address\"], .street-address'); if (!el) return ''; return el.textContent.replace(/\\s+/g, ' ').trim(); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "email",
            "selector": "(() => { const a = ROW.querySelector('a[href^=\"mailto:\"]'); return a ? a.getAttribute('href').replace(/^mailto:/i, '').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "telephone",
            "selector": "(() => { const el = ROW.querySelector('.phones.phone.primary, .phone.primary, a[href^=\"tel:\"], .phone, [itemprop=\"telephone\"]'); if (!el) return ''; return (el.getAttribute('href') || el.textContent).replace(/^tel:/i, '').replace(/\\s+/g, ' ').trim(); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "fax",
            "selector": "(() => { const txt = ROW.textContent.replace(/\\s+/g, ' '); const m = txt.match(/Fax[:\\s]*([+()\\d\\-.\\s]{7,})/i); return m ? m[1].trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "tollfree",
            "selector": "(() => { const txt = ROW.textContent.replace(/\\s+/g, ' '); const m = txt.match(/(?:Toll\\s*Free|TollFree)[:\\s]*([+()\\d\\-.\\s]{7,})/i); return m ? m[1].trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "website",
            "selector": "(() => { const a = ROW.querySelector('a.track-visit-website, a.website-link, a[href*=\"/redir\"], a[href^=\"http\"]:not([href*=\"superpages.com\"]):not([href*=\"yellowpages.com\"])'); return a ? a.href : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "social_media_links",
            "selector": "(() => Array.from(ROW.querySelectorAll('a[href*=\"facebook.com\"], a[href*=\"instagram.com\"], a[href*=\"twitter.com\"], a[href*=\"x.com\"], a[href*=\"linkedin.com\"], a[href*=\"youtube.com\"]')).map(a => a.href).join(' | '))()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "rating",
            "selector": "(() => { const el = ROW.querySelector('.rating, .result-rating, [class*=\"rating\"], [aria-label*=\"star\" i]'); if (!el) return ''; return (el.getAttribute('aria-label') || el.textContent).replace(/\\s+/g, ' ').trim(); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "review_count",
            "selector": "(() => { const el = ROW.querySelector('.count, .reviews, a[href*=\"reviews\"], [class*=\"review\"]'); if (!el) return ''; const txt = el.textContent.replace(/\\s+/g, ' ').trim(); const m = txt.match(/\\d+/); return m ? m[0] : txt; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "opening_hours",
            "selector": "(() => { const el = ROW.querySelector('.open-status, .hours, .hours-info, [class*=\"hours\"], [itemprop=\"openingHours\"]'); return el ? el.textContent.replace(/\\s+/g, ' ').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "description",
            "selector": "(() => { const el = ROW.querySelector('.snippet, .description, .listing-info, .body, [class*=\"description\"]'); return el ? el.textContent.replace(/\\s+/g, ' ').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "general_info",
            "selector": "(() => { const el = ROW.querySelector('.general-info, [class*=\"general\"], .snippet, .description'); return el ? el.textContent.replace(/\\s+/g, ' ').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "service_and_products",
            "selector": "(() => { const els = ROW.querySelectorAll('.services, .products, .categories a, .category a, a[href*=\"/category/\"]'); return Array.from(els).map(e => e.textContent.trim()).filter(Boolean).join(', '); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "primary_category",
            "selector": "(() => { const el = ROW.querySelector('.categories a, .category a, a[href*=\"/category/\"]'); return el ? el.textContent.replace(/\\s+/g, ' ').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "categories",
            "selector": "(() => { const els = ROW.querySelectorAll('.categories a, .category a, a[href*=\"/category/\"], .categories'); const vals = Array.from(els).map(e => e.textContent.replace(/\\s+/g, ' ').trim()).filter(Boolean); return Array.from(new Set(vals)).join(', '); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "price_range",
            "selector": "(() => { const el = ROW.querySelector('.price-range, [class*=\"price\"]'); return el ? el.textContent.replace(/\\s+/g, ' ').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "neighbourhoods",
            "selector": "(() => { const el = ROW.querySelector('.neighborhoods, .neighbourhoods, [class*=\"neighborhood\"], [class*=\"neighbourhood\"]'); return el ? el.textContent.replace(/\\s+/g, ' ').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "element-exists-1",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 1920,
      "position_y": 280,
      "config": {
        "selector": "a.next:not(.disabled):not([aria-disabled=\"true\"]), a[rel=\"next\"]:not(.disabled):not([aria-disabled=\"true\"]), .pagination a[aria-label*=\"Next\" i]:not(.disabled):not([aria-disabled=\"true\"])",
        "color": "bg-[#ff832b]"
      }
    },
    {
      "block_id": "click-1",
      "block_type": "process",
      "title": "Click",
      "description": "Click on element",
      "position_x": 2280,
      "position_y": 470,
      "config": {
        "selector": "a.next:not(.disabled):not([aria-disabled=\"true\"]), a[rel=\"next\"]:not(.disabled):not([aria-disabled=\"true\"]), .pagination a[aria-label*=\"Next\" i]:not(.disabled):not([aria-disabled=\"true\"])",
        "timeout": 10,
        "color": "bg-[#ff832b]"
      }
    },
    {
      "block_id": "wait-for-page-load-2",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 2640,
      "position_y": 470,
      "config": {
        "timeout": 30,
        "color": "bg-[#ff832b]"
      }
    },
    {
      "block_id": "wait-for-element-2",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 3000,
      "position_y": 470,
      "config": {
        "selector": ".search-results .result, .organic .result, div.result, article.result",
        "timeout": 30,
        "visible": true,
        "color": "bg-[#ff832b]"
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 3360,
      "position_y": 750,
      "config": {
        "duration": 2,
        "color": "bg-[#ff832b]"
      }
    },
    {
      "block_id": "end-1",
      "block_type": "output",
      "title": "End",
      "description": "Terminate execution flow",
      "position_x": 1920,
      "position_y": 650,
      "config": {
        "color": "bg-[#8d8d8d]"
      }
    }
  ],
  "connections": [
    {
      "from_block_id": "set-window-size-1",
      "from_connector_id": "right",
      "to_block_id": "navigate-1",
      "to_connector_id": "left"
    },
    {
      "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": "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": "element-exists-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-1",
      "from_connector_id": "true",
      "to_block_id": "click-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-1",
      "from_connector_id": "false",
      "to_block_id": "end-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "click-1",
      "from_connector_id": "right",
      "to_block_id": "wait-for-page-load-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-page-load-2",
      "from_connector_id": "right",
      "to_block_id": "wait-for-element-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-element-2",
      "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": "structured-export-1",
      "to_connector_id": "left"
    }
  ],
  "canvas_elements": [
    {
      "id": "group-entry",
      "element_type": "group",
      "title": "Entry & Setup",
      "color": "#4589ff",
      "position_x": 48,
      "position_y": 176,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "set-window-size-1"
        ]
      }
    },
    {
      "id": "group-load",
      "element_type": "group",
      "title": "Page Load",
      "color": "#08bdba",
      "position_x": 408,
      "position_y": 176,
      "width": 3200,
      "height": 766,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "wait-for-element-1",
          "wait-for-page-load-2",
          "wait-for-element-2",
          "sleep-1"
        ]
      }
    },
    {
      "id": "group-extract",
      "element_type": "group",
      "title": "Data Extraction",
      "color": "#42be65",
      "position_x": 1488,
      "position_y": 176,
      "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": 1848,
      "position_y": 176,
      "width": 680,
      "height": 486,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "element-exists-1",
          "click-1"
        ]
      }
    },
    {
      "id": "group-control",
      "element_type": "group",
      "title": "Control Flow",
      "color": "#8d8d8d",
      "position_x": 1848,
      "position_y": 546,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "end-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Best-effort UScraper equivalent of the Octoparse Superpages Details Page Scraper. Uses Superpages search for keyword=supermarket and location=95136, extracts Octoparse-like business lead fields from each result card, and clicks Next until no enabled next page is found. Output is appended across pages. Edit the Navigate URL and keyword/location JS constants for other inputs. Some detail-only fields may be empty if not present on listing cards.",
      "color": "#f1c21b",
      "position_x": 80,
      "position_y": 20,
      "width": 480,
      "height": 160,
      "z_index": 22,
      "data": {}
    },
    {
      "id": "note-block-structured-export-1",
      "element_type": "note",
      "title": "Note: Structured Export",
      "content": "Structured export with JS columns (keyword, location, detail_url, business_name, address). These selectors are fragile — update if the site layout changes.",
      "color": "#ee5396",
      "position_x": 1760,
      "position_y": 260,
      "width": 340,
      "height": 131,
      "z_index": 22,
      "data": {
        "block_id": "structured-export-1"
      }
    },
    {
      "id": "note-block-element-exists-1",
      "element_type": "note",
      "title": "Note: Element Exists",
      "content": "Condition block: checks `a.next:not(.disabled):not([aria-disabled=\"true\"]), a[rel=\"next\"]:not(.disabled):not([aria-disabled=\"true\"]), .pagination`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 2120,
      "position_y": 260,
      "width": 340,
      "height": 170,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-1"
      }
    },
    {
      "id": "note-block-click-1",
      "element_type": "note",
      "title": "Note: Click",
      "content": "Pagination click — add waits after this block; the page reloads asynchronously.",
      "color": "#ee5396",
      "position_x": 2480,
      "position_y": 450,
      "width": 316,
      "height": 106,
      "z_index": 22,
      "data": {
        "block_id": "click-1"
      }
    }
  ]
}