{
  "version": "1.0.0",
  "exported_at": "2026-06-01T14:00:00.000Z",
  "project": {
    "name": "Amazon Review Scraper for France",
    "description": "Best-effort Amazon France review scraper for ASIN B0F3CQCFJ7. Extracts page URL, ASIN, brand, product name/rating/count, review rating, reviewer, title, content, review link, image links, verified badge, helpful count, date, and country. Pagination uses Amazon's enabled Next button loop and appends all pages until the next button is disabled. Autonomous testing confirmed this environment is redirected to Amazon Sign In, so the template detects Sign In/CAPTCHA pages, saves a PNG blocker screenshot, and stops instead of exporting empty review data. A logged-in persistent browser profile, valid cookies, and possible anti-bot handling are required for successful review extraction.",
    "color": "bg-[#ff9900]",
    "template_id": "ai-generated"
  },
  "blocks": [
    {
      "block_id": "navigate-1",
      "block_type": "process",
      "title": "Navigate",
      "description": "Go to a URL",
      "position_x": 120,
      "position_y": 220,
      "config": {
        "url": "https://www.amazon.fr/product-reviews/B0F3CQCFJ7?sortBy=helpful&reviewerType=all_reviews&filterByStar=all_stars&formatType=all_formats&mediaType=all_contents&pageNumber=1&language=en_US",
        "color": "bg-[#ff9900]"
      }
    },
    {
      "block_id": "wait-for-page-load-1",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 456,
      "position_y": 220,
      "config": {
        "timeout": 30
      }
    },
    {
      "block_id": "inject-javascript-1",
      "block_type": "process",
      "title": "Inject JavaScript",
      "description": "Run custom JavaScript",
      "position_x": 792,
      "position_y": 220,
      "config": {
        "jsCode": "document.querySelector('#sp-cc-accept, input[name=\"accept\"], button[name=\"accept\"], [data-action-type=\"DISMISS\"]')?.click();",
        "waitForCompletion": true,
        "timeout": 5
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 1128,
      "position_y": 220,
      "config": {
        "duration": 1
      }
    },
    {
      "block_id": "element-exists-2",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 1464,
      "position_y": 220,
      "config": {
        "selector": "#ap_email, form[name='signIn'], #authportal-main-section, form[action*='validateCaptcha'], img[src*='captcha'], input[name='field-keywords'][aria-label*='captcha' i]"
      }
    },
    {
      "block_id": "take-screenshot-1",
      "block_type": "output",
      "title": "Take Screenshot",
      "description": "Capture current page",
      "position_x": 1800,
      "position_y": 520,
      "config": {
        "filename": "amazon_fr_signin_or_captcha_blocker.png",
        "fullPage": true,
        "saveFolder": "downloads"
      }
    },
    {
      "block_id": "wait-for-element-1",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 1464,
      "position_y": 520,
      "config": {
        "selector": "div[data-hook='review']",
        "timeout": 30,
        "visible": true
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 1968,
      "position_y": 800,
      "config": {
        "rowSelector": "div[data-hook='review']",
        "fileName": "amazon-commentaires-scraper.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "columns": [
          {
            "name": "Page_URL",
            "selector": "location.href",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "ASIN",
            "selector": "(location.pathname.match(/product-reviews\\/([A-Z0-9]{10})/) || location.href.match(/\\/([A-Z0-9]{10})(?:[/?]|$)/) || [])[1] || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Brand",
            "selector": "(() => { const t=(document.querySelector('[data-hook=\"product-link\"], #cm_cr-product_info a.a-link-normal, a[data-hook=\"product-link\"]')?.textContent || '').trim(); const b=(document.querySelector('[data-hook=\"cr-product-byline\"], #bylineInfo')?.textContent || '').replace(/^Brand:\\s*/i,'').trim(); return b || (t.split(/\\s+/)[0] || ''); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Nom_produit",
            "selector": "(() => (document.querySelector('[data-hook=\"product-link\"], #cm_cr-product_info a.a-link-normal, h1 a, h1')?.textContent || '').trim())()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Note_produit",
            "selector": "(() => (document.querySelector('[data-hook=\"rating-out-of-text\"], [data-hook=\"average-star-rating\"] .a-icon-alt, #cm_cr-product_info .a-icon-alt')?.textContent || '').trim())()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Nombre_avis",
            "selector": "(() => (document.querySelector('[data-hook=\"total-review-count\"], [data-hook=\"cr-filter-info-review-rating-count\"], #filter-info-section')?.textContent || '').trim())()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Note_avis",
            "selector": "(ROW.querySelector('[data-hook=\"review-star-rating\"] span, [data-hook=\"cmps-review-star-rating\"] span, i[data-hook=\"review-star-rating\"], i[data-hook=\"cmps-review-star-rating\"], .review-rating')?.textContent || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Auteur_avis",
            "selector": "(ROW.querySelector('.a-profile-name')?.textContent || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Titre_avis",
            "selector": "(() => { const el=ROW.querySelector('[data-hook=\"review-title\"]'); if(!el) return ''; const parts=Array.from(el.querySelectorAll('span')).map(s => s.textContent.trim()).filter(Boolean); return parts.length ? parts[parts.length - 1] : el.textContent.trim(); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Contenu_avis",
            "selector": "(ROW.querySelector('[data-hook=\"review-body\"] span, [data-hook=\"review-body\"], .review-text')?.textContent || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Lien_avis",
            "selector": "(() => { const a=ROW.querySelector('a[data-hook=\"review-title\"], [data-hook=\"review-title\"]'); return a && a.href ? a.href : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Liens_images",
            "selector": "Array.from(ROW.querySelectorAll('img[data-hook=\"review-image-tile\"], .review-image-tile img, img.review-image-tile')).map(img => img.currentSrc || img.src).filter(Boolean).join(';')",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Avis_verifie",
            "selector": "ROW.querySelector('[data-hook=\"avp-badge\"], .avp-badge') ? 'True' : 'False'",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Nombre_avis_utiles",
            "selector": "(ROW.querySelector('[data-hook=\"helpful-vote-statement\"]')?.textContent || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Date",
            "selector": "(ROW.querySelector('[data-hook=\"review-date\"]')?.textContent || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Pays",
            "selector": "(() => { const d=(ROW.querySelector('[data-hook=\"review-date\"]')?.textContent || '').trim(); const m=d.match(/(?:Reviewed|Commenté)\\s+(?:in|en|au|aux)\\s+(.+?)\\s+(?:on|le)\\s+/i); return m ? m[1].trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "element-exists-1",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 2304,
      "position_y": 800,
      "config": {
        "selector": ".a-pagination li.a-last:not(.a-disabled) a, ul.a-pagination li:last-child:not(.a-disabled) a"
      }
    },
    {
      "block_id": "click-1",
      "block_type": "process",
      "title": "Click",
      "description": "Click on element",
      "position_x": 2640,
      "position_y": 800,
      "config": {
        "selector": ".a-pagination li.a-last:not(.a-disabled) a, ul.a-pagination li:last-child:not(.a-disabled) a",
        "timeout": 10
      }
    },
    {
      "block_id": "wait-for-page-load-2",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 2976,
      "position_y": 800,
      "config": {
        "timeout": 30
      }
    },
    {
      "block_id": "element-exists-3",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 3312,
      "position_y": 800,
      "config": {
        "selector": "#ap_email, form[name='signIn'], #authportal-main-section, form[action*='validateCaptcha'], img[src*='captcha'], input[name='field-keywords'][aria-label*='captcha' i]"
      }
    },
    {
      "block_id": "take-screenshot-2",
      "block_type": "output",
      "title": "Take Screenshot",
      "description": "Capture current page",
      "position_x": 3648,
      "position_y": 800,
      "config": {
        "filename": "amazon_fr_pagination_signin_or_captcha_blocker.png",
        "fullPage": true,
        "saveFolder": "downloads"
      }
    },
    {
      "block_id": "wait-for-element-2",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 3984,
      "position_y": 800,
      "config": {
        "selector": "div[data-hook='review']",
        "timeout": 30,
        "visible": true
      }
    },
    {
      "block_id": "sleep-2",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 4320,
      "position_y": 800,
      "config": {
        "duration": 2
      }
    },
    {
      "block_id": "end-1",
      "block_type": "output",
      "title": "End",
      "description": "Terminate execution flow",
      "position_x": 4656,
      "position_y": 800,
      "config": {}
    }
  ],
  "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": "element-exists-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-2",
      "from_connector_id": "true",
      "to_block_id": "take-screenshot-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-2",
      "from_connector_id": "false",
      "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": "element-exists-3",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-3",
      "from_connector_id": "true",
      "to_block_id": "take-screenshot-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-3",
      "from_connector_id": "false",
      "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-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-2",
      "from_connector_id": "right",
      "to_block_id": "structured-export-1",
      "to_connector_id": "left"
    }
  ],
  "canvas_elements": [
    {
      "id": "group-load",
      "element_type": "group",
      "title": "Page Load",
      "color": "#08bdba",
      "position_x": 48,
      "position_y": 116,
      "width": 4520,
      "height": 876,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "sleep-1",
          "wait-for-element-1",
          "wait-for-page-load-2",
          "wait-for-element-2",
          "sleep-2"
        ]
      }
    },
    {
      "id": "group-interaction",
      "element_type": "group",
      "title": "Interaction",
      "color": "#a56eff",
      "position_x": 720,
      "position_y": 116,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "inject-javascript-1"
        ]
      }
    },
    {
      "id": "group-pagination",
      "element_type": "group",
      "title": "Pagination Loop",
      "color": "#ff832b",
      "position_x": 1392,
      "position_y": 116,
      "width": 2168,
      "height": 876,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "element-exists-2",
          "element-exists-1",
          "click-1",
          "element-exists-3"
        ]
      }
    },
    {
      "id": "group-extract",
      "element_type": "group",
      "title": "Data Extraction",
      "color": "#42be65",
      "position_x": 1728,
      "position_y": 416,
      "width": 2168,
      "height": 576,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "take-screenshot-1",
          "structured-export-1",
          "take-screenshot-2"
        ]
      }
    },
    {
      "id": "group-control",
      "element_type": "group",
      "title": "Control Flow",
      "color": "#8d8d8d",
      "position_x": 4584,
      "position_y": 696,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "end-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Best-effort Amazon France review scraper for ASIN B0F3CQCFJ7. Extracts page URL, ASIN, brand, product name/rating/count, review rating, reviewer, title, content, review link, image links, verified badge, helpful count, date, and country. Pagination uses Amazon's enabled Next button loop and appends all pages until the next button is disabled. Autonomous testing confirmed this environment is redirected to Amazon Sign In, so the template detects Sign In/CAPTCHA pages, saves a PNG blocker screenshot, and stops instead of exporting empty review data. A logged-in persistent browser profile, valid cookies, and possible anti-bot handling are required for successful review extraction.",
      "color": "#f1c21b",
      "position_x": 80,
      "position_y": 20,
      "width": 480,
      "height": 160,
      "z_index": 22,
      "data": {}
    },
    {
      "id": "note-block-inject-javascript-1",
      "element_type": "note",
      "title": "Note: Inject JavaScript",
      "content": "Runs custom JavaScript in the page: `document.querySelector('#sp-cc-accept, input[name=\"accept\"], button[name=\"accept\"], [data-action-typ...` Verify in browser if results are empty.",
      "color": "#ee5396",
      "position_x": 992,
      "position_y": 200,
      "width": 340,
      "height": 140,
      "z_index": 22,
      "data": {
        "block_id": "inject-javascript-1"
      }
    },
    {
      "id": "note-block-element-exists-2",
      "element_type": "note",
      "title": "Note: Element Exists",
      "content": "Condition block: checks `#ap_email, form[name='signIn'], #authportal-main-section, form[action*='validateCaptcha'], img[src*='captcha'], input[na`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 1664,
      "position_y": 200,
      "width": 340,
      "height": 170,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-2"
      }
    },
    {
      "id": "note-block-structured-export-1",
      "element_type": "note",
      "title": "Note: Structured Export",
      "content": "Structured export with JS columns (Page_URL, ASIN, Brand, Nom_produit, Note_produit). These selectors are fragile — update if the site layout changes.",
      "color": "#ee5396",
      "position_x": 2168,
      "position_y": 780,
      "width": 340,
      "height": 130,
      "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-pagination li.a-last:not(.a-disabled) a, ul.a-pagination li:last-child:not(.a-disabled) a`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 2504,
      "position_y": 780,
      "width": 340,
      "height": 161,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-1"
      }
    },
    {
      "id": "note-block-element-exists-3",
      "element_type": "note",
      "title": "Note: Element Exists",
      "content": "Condition block: checks `#ap_email, form[name='signIn'], #authportal-main-section, form[action*='validateCaptcha'], img[src*='captcha'], input[na`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 3512,
      "position_y": 780,
      "width": 340,
      "height": 170,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-3"
      }
    }
  ]
}