Prompt: Build a workflow for: Keyword Rank Tracker Google Sheets

Response:
# Workflow Architecture

**Purpose**: General Automation

**Key Components**:
- Total Nodes: 30
- Node Types: n8n-nodes-base.splitOut, n8n-nodes-base.set, n8n-nodes-base.splitInBatches, n8n-nodes-base.limit, n8n-nodes-base.if, n8n-nodes-base.manualTrigger, n8n-nodes-base.sort, n8n-nodes-base.stickyNote, n8n-nodes-base.code, n8n-nodes-base.googleBigQuery

**Logic Flow**:
1. **Trigger**: n8n-nodes-base.manualTrigger - Initiates the workflow

## Complete Workflow JSON

```json
{
  "name": "keyword_rank_tracker_google_sheets",
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        260,
        820
      ],
      "id": "8acb9df9-dae5-41ec-b899-0cfb7c3853ea",
      "name": "When clicking ‘Test workflow’"
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "1AJRIe-IROQGRtqlBqeiyVP5ayjSlfOMC_nFDGwwLULU",
          "mode": "list",
          "cachedResultName": "tracked_keywords",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1AJRIe-IROQGRtqlBqeiyVP5ayjSlfOMC_nFDGwwLULU/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $json.domain }}",
          "mode": "name"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1340,
        280
      ],
      "id": "86f7ea65-9942-4886-9516-21553ac7a460",
      "name": "Get Tracked Keywords"
    },
    {
      "parameters": {
        "jsCode": "return [{\n  json: {\n    keywordString: $input.all().map(item => `'${item.json.keywords}'`).join(', ')\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1580,
        280
      ],
      "id": "3ca647b4-2613-4b31-b1da-9724911380ca",
      "name": "Code"
    },
    {
      "parameters": {
        "projectId": {
          "__rl": true,
          "value": "automations-451008",
          "mode": "list",
          "cachedResultName": "automations",
          "cachedResultUrl": "https://console.cloud.google.com/bigquery?project=automations-451008"
        },
        "sqlQuery": "WITH daily_metrics AS (\n  SELECT \n    data_date as date,\n    query as keyword,\n    url,\n    device,\n    SUM(clicks) as clicks,\n    SUM(impressions) as impressions,\n    ROUND(AVG(sum_position / impressions), 1) as position,\n    ROUND(SUM(clicks) / SUM(impressions) * 100, 2) as ctr\n  FROM `{{ $('Loop Over Items').all()[0].json.searchdata_url_impression }}`\n  WHERE \n    data_date > '{{ $('Merge Loop Data').all()[0].json.date }}'\n    AND NOT is_anonymized_query\n    AND lower(query) IN (\n    {{ $('Merge Loop Data').all()[1].json.keywordString }}\n    )\n  -- remove following line if you want to exclude toc rankings\n  AND url NOT LIKE '%#%'\n  GROUP BY date, keyword, url, device\n)\n\nSELECT \n  date,\n  keyword,\n  device,\n  url,\n  clicks,\n  impressions,\n  position,\n  ctr\nFROM daily_metrics\nORDER BY date ASC, keyword, position ASC",
        "options": {}
      },
      "type": "n8n-nodes-base.googleBigQuery",
      "typeVersion": 2.1,
      "position": [
        2540,
        260
      ],
      "id": "f9245333-7f36-42f8-85c4-502ab8c15b92",
      "name": "Get Ranking Keywords by URL",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "19wCg-VAykAIYzeryWTeLfxJEr9G9Sj1Vf3h4DZUITqQ",
          "mode": "list",
          "cachedResultName": "rank_tracking",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/19wCg-VAykAIYzeryWTeLfxJEr9G9Sj1Vf3h4DZUITqQ/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $('Loop Over Items').all()[0].json.domain }}",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "date": "={{ $json.date }}",
            "keyword": "={{ $json.keyword }}",
            "url": "={{ $json.url }}",
            "device": "={{ $json.device }}",
            "clicks": "={{ $json.clicks }}",
            "position": "={{ $json.position }}",
            "ctr": "={{ $json.ctr }}",
            "impressions": "={{ $json.impressions }}"
          },
          "matchingColumns": [
            "date"
          ],
          "schema": [
            {
              "id": "date",
              "displayName": "date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "url",
              "displayName": "url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "device",
              "displayName": "device",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "keyword",
              "displayName": "keyword",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "clicks",
              "displayName": "clicks",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions",
              "displayName": "impressions",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "position",
              "displayName": "position",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "ctr",
              "displayName": "ctr",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        2740,
        260
      ],
      "id": "47bd9243-26d3-4ba6-ae65-f3cbc86e7020",
      "name": "Insert URL Rankings"
    },
    {
      "parameters": {
        "mode": "raw",
        "jsonOutput": "{\n  \"domains\": [\n    {\n      \"domain\": \"domain_1\",\n      \"searchdata_url_impression\": \"searchdata_url_impression\",\n      \"searchdata_site_impression\": \"searchdata_site_impression\"\n    },\n    {\n      \"domain\": \"domain_2\",\n      \"searchdata_url_impression\": \"searchdata_url_impression\",\n      \"searchdata_site_impression\": \"searchdata_site_impression\"\n    }\n  ]\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        460,
        820
      ],
      "id": "204a8fdf-f163-4c72-99b5-1babc3f1cdfd",
      "name": "Domains"
    },
    {
      "parameters": {
        "fieldToSplitOut": "domains",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        640,
        820
      ],
      "id": "e2d43fb3-20f1-433a-8b0e-a7aca6c28546",
      "name": "Split Out"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        980,
        180
      ],
      "id": "3e131334-a028-4513-999d-fedbe8ec1ec3",
      "name": "Loop Over Items"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        2340,
        260
      ],
      "id": "1db25f6f-9684-4c18-adbf-8f11a792cda8",
      "name": "Merge Loop Data"
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "19wCg-VAykAIYzeryWTeLfxJEr9G9Sj1Vf3h4DZUITqQ",
          "mode": "list",
          "cachedResultName": "rank_tracking",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/19wCg-VAykAIYzeryWTeLfxJEr9G9Sj1Vf3h4DZUITqQ/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $json.domain }}",
          "mode": "name"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1340,
        120
      ],
      "id": "ef8f0f8e-eef5-4528-a875-1c9d9af7682a",
      "name": "Google Sheets",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "sortFieldsUi": {
          "sortField": [
            {
              "fieldName": "date"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.sort",
      "typeVersion": 1,
      "position": [
        1820,
        40
      ],
      "id": "d817e09f-c5a0-40a5-bbf6-64bc606b0796",
      "name": "Sort"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "1a376642-1bb3-43a3-802f-6844d3b9c2a7",
              "leftValue": "={{ $('Google Sheets').all()[0].json.isEmpty()}}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1580,
        120
      ],
      "id": "3dd0c3e7-3898-4204-968c-6395f76303f2",
      "name": "If"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "e3ce8bf6-cbee-4949-a338-aeb1523b646a",
              "name": "=date",
              "value": "={{ $now.minus({ days: 7 }).format('yyyy-MM-dd') }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1820,
        220
      ],
      "id": "661b773d-3c02-4060-a023-407e2e981e2f",
      "name": "Set Date",
      "notes": "In case the pipeline has not been triggered before, then the tracking sheet is empty. If true, we will take as a starting point of today minus 7 days. "
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "4538ac52-c81c-460f-96ce-70ab74f313d9",
              "name": "date",
              "value": "={{ $json.date }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        2100,
        40
      ],
      "id": "13c62280-43b6-4e5e-9f24-9d4c2adf27ec",
      "name": "Get date"
    },
    {
      "parameters": {
        "keep": "lastItems"
      },
      "type": "n8n-nodes-base.limit",
      "typeVersion": 1,
      "position": [
        1960,
        40
      ],
      "id": "4981a6af-44e3-43ca-bcbe-89540045278d",
      "name": "Get latest row"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        980,
        580
      ],
      "id": "0a3fe253-e489-4cf2-aea7-c3933b18e65c",
      "name": "Loop Over Items1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "32ae47a9-f7f5-41fc-b403-468094ba3f41",
              "leftValue": "={{ $('Get Top Ranking Keywords Date').all()[0].json.isEmpty()}}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1360,
        680
      ],
      "id": "9e74b6c0-d63b-497e-a45f-860ef1680a8e",
      "name": "If1"
    },
    {
      "parameters": {
        "sortFieldsUi": {
          "sortField": [
            {
              "fieldName": "data_date"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.sort",
      "typeVersion": 1,
      "position": [
        1600,
        540
      ],
      "id": "90662893-eeb1-4b70-8e63-22dbc1691932",
      "name": "Sort1"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "4538ac52-c81c-460f-96ce-70ab74f313d9",
              "name": "date",
              "value": "={{ $json.data_date }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1920,
        540
      ],
      "id": "6ea5970f-2a06-4334-89a3-e5a2234f38af",
      "name": "Get date1"
    },
    {
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "1KWs-hsuxs_5leU6qELEDlzpFObkhHAFdKgJmDVq5aKg",
          "mode": "list",
          "cachedResultName": "Top Ranking Keywords",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1KWs-hsuxs_5leU6qELEDlzpFObkhHAFdKgJmDVq5aKg/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $('Loop Over Items1').item.json.domain }}",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "data_date": "={{ $json.data_date }}",
            "query": "={{ $json.query }}",
            "url": "={{ $json.url }}",
            "device": "={{ $json.device }}",
            "result_type": "={{ $json.result_type }}",
            "total_impressions": "={{ $json.total_impressions }}",
            "total_clicks": "={{ $json.total_clicks }}",
            "avg_position": "={{ $json.avg_position }}",
            "ctr_percentage": "={{ $json.ctr_percentage }}",
            "position_bucket": "={{ $json.position_bucket }}"
          },
          "matchingColumns": [
            "data_date"
          ],
          "schema": [
            {
              "id": "data_date",
              "displayName": "data_date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "query",
              "displayName": "query",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "displayName": "url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "device",
              "displayName": "device",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "result_type",
              "displayName": "result_type",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "total_impressions",
              "displayName": "total_impressions",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "total_clicks",
              "displayName": "total_clicks",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "avg_position",
              "displayName": "avg_position",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "ctr_percentage",
              "displayName": "ctr_percentage",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "position_bucket",
              "displayName": "position_bucket",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        2360,
        740
      ],
      "id": "0c6efb69-c1c2-47cd-a81e-6d6489796456",
      "name": "Insert Top Ranking Keywords"
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "1KWs-hsuxs_5leU6qELEDlzpFObkhHAFdKgJmDVq5aKg",
          "mode": "list",
          "cachedResultName": "Top Ranking Keywords",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1KWs-hsuxs_5leU6qELEDlzpFObkhHAFdKgJmDVq5aKg/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $json.domain }}",
          "mode": "name"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1200,
        680
      ],
      "id": "9d071923-bc79-45f8-967e-5f610bb8aa12",
      "name": "Get Top Ranking Keywords Date",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "keep": "lastItems"
      },
      "type": "n8n-nodes-base.limit",
      "typeVersion": 1,
      "position": [
        1760,
        540
      ],
      "id": "fe61c0ef-99bc-4f00-89ff-fbd09333e88b",
      "name": "Get last row by date"
    },
    {
      "parameters": {
        "projectId": {
          "__rl": true,
          "value": "automations-451008",
          "mode": "list",
          "cachedResultName": "automations",
          "cachedResultUrl": "https://console.cloud.google.com/bigquery?project=automations-451008"
        },
        "sqlQuery": "WITH filtered_queries AS (\n  SELECT \n    data_date,\n    device,\n    query,\n    url,\n    SUM(clicks) as clicks,\n    SUM(impressions) as impressions,\n    SUM(sum_position) as sum_position,\n    SUM(sum_position)/SUM(impressions) + 1 as avg_position,\n    MAX(CASE \n      WHEN is_tpf_faq THEN 'FAQ'\n      WHEN is_tpf_howto THEN 'HowTo'\n      WHEN is_review_snippet THEN 'Review'\n      ELSE 'Normal'\n    END) as result_type\n  FROM `{{ $('Loop Over Items1').all()[0].json.searchdata_url_impression }}`\n  WHERE SAFE_DIVIDE(sum_position, impressions) <= 50\n  AND is_anonymized_query = False\n  AND impressions >= 5\n  AND data_date > '{{ $json.date }}'\n  GROUP BY data_date, device, query, url\n)\n\nSELECT \n  data_date,\n  query,\n  url,\n  device,\n  result_type,\n  impressions as total_impressions,\n  clicks as total_clicks,\n  avg_position,\n  SAFE_DIVIDE(clicks, impressions) * 100 as ctr_percentage,\n  CASE \n    WHEN avg_position <= 3 THEN 'Top 3'\n    WHEN avg_position <= 10 THEN 'Top 10'\n    WHEN avg_position <= 20 THEN 'Top 20'\n    ELSE 'Above 20'\n  END as position_bucket\nFROM filtered_queries\nORDER BY \n  data_date DESC,\n  url",
        "options": {}
      },
      "type": "n8n-nodes-base.googleBigQuery",
      "typeVersion": 2.1,
      "position": [
        2140,
        740
      ],
      "id": "a425bbf8-2dc2-4c5a-a870-423b1e4b6266",
      "name": "Get Keyword Opportunities",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "e3ce8bf6-cbee-4949-a338-aeb1523b646a",
              "name": "=date",
              "value": "={{ $now.minus({ days: 7 }).format('yyyy-MM-dd') }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1600,
        760
      ],
      "id": "b2101d06-4890-40bc-b7ba-40726f57f195",
      "name": "Today - 7d",
      "notes": "In case the pipeline has not been triggered before, then the tracking sheet is empty. If true, we will take as a starting point of today minus 7 days. "
    },
    {
      "parameters": {
        "content": "# Keyword Tracking by Keyword List",
        "height": 480,
        "width": 2120
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        840,
        0
      ],
      "id": "d53bc40e-ef62-4800-8909-da9e5435dd1e",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "# Keywords by URL and Top position",
        "height": 480,
        "width": 2120
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        840,
        500
      ],
      "id": "07c0101b-efbf-4bc9-bbc5-610145c44daf",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "# Instructions\n\n## Description\nThis automation enables you to replace expensive SEO Rank Trackers and track any number of keywords for multiple domains.\n\n## Requirements & Setup (~20 minutes)\nTo use this template, you need bulk export enabled for your property connected to Google Search Console. The automation uses a BigQuery table for data processing.\n\nYou'll also need to set up credentials for accessing both BigQuery and Google Sheets.\n\n## Google Spreadsheets\nThis automation requires three spreadsheets:\n1. **Top Ranking Keywords**: Saves queries where you already rank at a decent position. This data helps identify low-hanging fruits.\n   - Columns: data_date, query, url, device, result_type, total_impressions, total_clicks, avg_position, ctr_percentage, position_bucket\n\n2. **Rank Tracking**: Tracks the daily performance of your monitored keywords.\n   - Columns: date, url, device, keyword, clicks, impressions, position, ctr\n\n3. **Tracked Keywords**: Stores all keywords you want to rank for.\n   - Columns: domain, keyword\n",
        "height": 980,
        "width": 640
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        180,
        0
      ],
      "id": "485c6d22-ac32-4024-926f-2768e008ffcb",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "adjust this node if you want to start with more historical data\n",
        "height": 200,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1580,
        680
      ],
      "id": "c04010cc-692c-4aac-9f30-a310d0ec4d5d",
      "name": "Sticky Note3"
    },
    {
      "parameters": {
        "content": "adjust this node if you want to start with more historical data\n",
        "height": 200,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1780,
        160
      ],
      "id": "4b6fd09a-cb3d-4a8f-840d-9426e19dc83d",
      "name": "Sticky Note4"
    },
    {
      "parameters": {
        "content": "add your domains and tables here",
        "height": 180,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        400,
        780
      ],
      "id": "1994ac61-8221-450a-a17e-4480f4bc5e2c",
      "name": "Sticky Note5"
    }
  ],
  "pinData": {},
  "connections": {
    "When clicking ‘Test workflow’": {
      "main": [
        [
          {
            "node": "Domains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Tracked Keywords": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Merge Loop Data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get Ranking Keywords by URL": {
      "main": [
        [
          {
            "node": "Insert URL Rankings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert URL Rankings": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Domains": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Get Tracked Keywords",
            "type": "main",
            "index": 0
          },
          {
            "node": "Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Loop Data": {
      "main": [
        [
          {
            "node": "Get Ranking Keywords by URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sort": {
      "main": [
        [
          {
            "node": "Get latest row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If": {
      "main": [
        [
          {
            "node": "Sort",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set Date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Date": {
      "main": [
        [
          {
            "node": "Merge Loop Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get date": {
      "main": [
        [
          {
            "node": "Merge Loop Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get latest row": {
      "main": [
        [
          {
            "node": "Get date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items1": {
      "main": [
        [],
        [
          {
            "node": "Get Top Ranking Keywords Date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sort1": {
      "main": [
        [
          {
            "node": "Get last row by date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If1": {
      "main": [
        [
          {
            "node": "Sort1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Today - 7d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Top Ranking Keywords Date": {
      "main": [
        [
          {
            "node": "If1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get last row by date": {
      "main": [
        [
          {
            "node": "Get date1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get date1": {
      "main": [
        [
          {
            "node": "Get Keyword Opportunities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert Top Ranking Keywords": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Keyword Opportunities": {
      "main": [
        [
          {
            "node": "Insert Top Ranking Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Today - 7d": {
      "main": [
        [
          {
            "node": "Get Keyword Opportunities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "9181a9fe-0814-443c-86b3-d5237f88f693",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "558d88703fb65b2d0e44613bc35916258b0f0bf983c5d4730c00c424b77ca36a"
  },
  "id": "nOzLedRb5STlMLxP",
  "tags": [
    {
      "createdAt": "2025-03-02T12:05:53.836Z",
      "updatedAt": "2025-03-02T12:05:53.836Z",
      "id": "utwtHTzeqUdktrxJ",
      "name": "SEO"
    },
    {
      "createdAt": "2025-03-12T18:27:08.298Z",
      "updatedAt": "2025-03-12T18:27:08.298Z",
      "id": "LJnByXT8PNh6CBUf",
      "name": "templates"
    }
  ]
}
```


Prompt: How would you build: Rank Tracker Postgres Template?

Response:
# Workflow Architecture

**Purpose**: General Automation

**Key Components**:
- Total Nodes: 28
- Node Types: n8n-nodes-base.splitOut, n8n-nodes-base.set, n8n-nodes-base.splitInBatches, n8n-nodes-base.postgres, n8n-nodes-base.if, n8n-nodes-base.manualTrigger, n8n-nodes-base.stickyNote, n8n-nodes-base.code, n8n-nodes-base.googleBigQuery, n8n-nodes-base.merge

**Logic Flow**:
1. **Trigger**: n8n-nodes-base.manualTrigger - Initiates the workflow

## Complete Workflow JSON

```json
{
  "name": "Rank Tracker Postgres Template",
  "nodes": [
    {
      "parameters": {
        "projectId": {
          "__rl": true,
          "value": "automations-451008",
          "mode": "list",
          "cachedResultName": "automations",
          "cachedResultUrl": "https://console.cloud.google.com/bigquery?project=automations-451008"
        },
        "sqlQuery": "WITH daily_metrics AS (\n  SELECT \n    data_date as date,\n    query as keyword,\n    url,\n    device,\n    SUM(clicks) as clicks,\n    SUM(impressions) as impressions,\n    ROUND(AVG(sum_position / impressions), 1) as position,\n    ROUND(SUM(clicks) / SUM(impressions) * 100, 2) as ctr\n  FROM `{{ $('Loop Over Items').all()[0].json.searchdata_url_impression }}`\n  WHERE\n    data_date > '{{ $json.data_date }}'\n    AND NOT is_anonymized_query\n    AND lower(query) IN (\n   {{ $('merge_query_params').all()[1].json.keywordString }}\n    )\n  -- remove following line if you want to exclude toc rankings\n  AND url NOT LIKE '%#%'\n  GROUP BY date, keyword, url, device\n)\n\nSELECT \n  date,\n  keyword,\n  device,\n  url,\n  clicks,\n  impressions,\n  position,\n  ctr\nFROM daily_metrics\nORDER BY date ASC, keyword, position ASC",
        "options": {}
      },
      "type": "n8n-nodes-base.googleBigQuery",
      "typeVersion": 2.1,
      "position": [
        560,
        820
      ],
      "id": "889ee8e9-7476-4a87-b791-4718c05664f4",
      "name": "Get Ranking Keywords by URL",
      "alwaysOutputData": false,
      "executeOnce": true
    },
    {
      "parameters": {
        "mode": "raw",
        "jsonOutput": "{\n  \"domains\": [\n    {\n      \"domain\": \"domain\",\n      \"searchdata_url_impression\": \"searchdata_url_impression\",\n      \"searchdata_site_impression\": \"searchdata_site_impression\"\n    },\n\n  ]\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -60,
        440
      ],
      "id": "3f315b4a-6f55-4870-bc56-e032b4516fca",
      "name": "Domains"
    },
    {
      "parameters": {
        "fieldToSplitOut": "domains",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        160,
        440
      ],
      "id": "a16cff0d-b2f5-431d-b2a2-82aaba6564c7",
      "name": "Split Out"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        -500,
        860
      ],
      "id": "5984e986-17d6-4ac8-ab02-3f9f2860ba7b",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "1a376642-1bb3-43a3-802f-6844d3b9c2a7",
              "leftValue": "={{ $('get_date_of_last_run').all()[0].json.isEmpty()}}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -100,
        800
      ],
      "id": "670742c9-0640-4489-92f0-81a1d1a85e2d",
      "name": "If"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        1120,
        900
      ],
      "id": "c9de6b4c-7be7-4421-b924-224adcbc7f38",
      "name": "Loop Over Items1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "32ae47a9-f7f5-41fc-b403-468094ba3f41",
              "leftValue": "={{ $('get_date_of_last_run_1').all()[0].json.isEmpty()}}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1520,
        920
      ],
      "id": "b6171a4a-5059-4744-bc09-248c30b3a1b6",
      "name": "If1"
    },
    {
      "parameters": {
        "projectId": {
          "__rl": true,
          "value": "automations-451008",
          "mode": "list",
          "cachedResultName": "automations",
          "cachedResultUrl": "https://console.cloud.google.com/bigquery?project=automations-451008"
        },
        "sqlQuery": "WITH filtered_queries AS (\n  SELECT \n    data_date,\n    device,\n    query,\n    url,\n    SUM(clicks) as clicks,\n    SUM(impressions) as impressions,\n    SUM(sum_position) as sum_position,\n    SUM(sum_position)/SUM(impressions) + 1 as avg_position,\n    MAX(CASE \n      WHEN is_tpf_faq THEN 'FAQ'\n      WHEN is_tpf_howto THEN 'HowTo'\n      WHEN is_review_snippet THEN 'Review'\n      ELSE 'Normal'\n    END) as result_type\n  FROM `{{ $('Loop Over Items1').all()[0].json.searchdata_url_impression }}`\n  WHERE SAFE_DIVIDE(sum_position, impressions) <= 50\n  AND is_anonymized_query = False\n  AND impressions >= 5\n  AND data_date > '{{ $json.data_date }}'\n  GROUP BY data_date, device, query, url\n)\n\nSELECT \n  data_date,\n  query,\n  url,\n  device,\n  result_type,\n  impressions as total_impressions,\n  clicks as total_clicks,\n  avg_position,\n  SAFE_DIVIDE(clicks, impressions) * 100 as ctr_percentage,\n  CASE \n    WHEN avg_position <= 3 THEN 'Top 3'\n    WHEN avg_position <= 10 THEN 'Top 10'\n    WHEN avg_position <= 20 THEN 'Top 20'\n    ELSE 'Above 20'\n  END as position_bucket\nFROM filtered_queries\nORDER BY \n  data_date DESC,\n  url",
        "options": {}
      },
      "type": "n8n-nodes-base.googleBigQuery",
      "typeVersion": 2.1,
      "position": [
        2040,
        920
      ],
      "id": "0bf4672c-43d7-46d9-8ed5-7632f68823ee",
      "name": "Get Keyword Opportunities",
      "alwaysOutputData": false,
      "executeOnce": true
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT data_date FROM rank_tracking_by_keywords WHERE domain = '{{ $json.domain }}' ORDER BY data_date DESC LIMIT 1;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        -280,
        800
      ],
      "id": "715b6742-1bfa-4149-b9de-b87f279b1c9f",
      "name": "get_date_of_last_run",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT keyword from tracked_keywords WHERE domain = '{{ $json.domain }}'",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        -280,
        960
      ],
      "id": "4a3dad81-fef3-42a3-88b6-217219981f24",
      "name": "get_keywords_to_track"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        340,
        820
      ],
      "id": "68d1a031-b956-4298-a8b4-7531111641d5",
      "name": "merge_query_params"
    },
    {
      "parameters": {
        "jsCode": "function getKeywordsString(inputArray) {\n    return inputArray.map(item => `'${item.json.keyword}'`).join(', ');\n}\n\nreturn [{\n    json: {\n        keywordString: getKeywordsString($input.all())\n    }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        100,
        1040
      ],
      "id": "fb85991b-1d6b-4b84-b795-3018b2c6ed2f",
      "name": "concat_keywords"
    },
    {
      "parameters": {
        "jsCode": "return [{\n  data_date: $input.first().json.data_date.split('T')[0]\n}]"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        100,
        640
      ],
      "id": "511965b1-d6e7-4744-bdda-a36b2aee5d9e",
      "name": "get_date"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT data_date FROM top_ranking_keywords WHERE domain = '{{ $json.domain }}' ORDER BY data_date DESC LIMIT 1;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        1340,
        920
      ],
      "id": "4dd56d48-af92-40f1-8797-ed7a78b39cb7",
      "name": "get_date_of_last_run_1",
      "alwaysOutputData": true
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        1880,
        920
      ],
      "id": "ef6d77f2-eaec-4ab6-9dd0-7b565d3488ff",
      "name": "merge_query_params_1"
    },
    {
      "parameters": {
        "jsCode": "return [{\n  data_date: $input.first().json.data_date.split('T')[0]\n}]"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1700,
        840
      ],
      "id": "4d5c6f59-642a-46c3-acab-13ab42a4a992",
      "name": "get_date_1",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "operation": "upsert",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "rank_tracking_by_keywords",
          "mode": "list",
          "cachedResultName": "rank_tracking_by_keywords"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "data_date": "={{ $json.date }}",
            "clicks": "={{ $json.clicks }}",
            "impressions": "={{ $json.impressions }}",
            "position": "={{ $json.position }}",
            "ctr": "={{ $json.ctr }}",
            "url": "={{ $json.url }}",
            "keyword": "={{ $json.keyword }}",
            "device": "={{ $json.device }}",
            "domain": "={{ $('Loop Over Items').item.json.domain }}"
          },
          "matchingColumns": [
            "data_date",
            "url",
            "keyword"
          ],
          "schema": [
            {
              "id": "data_date",
              "displayName": "data_date",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "url",
              "displayName": "url",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "device",
              "displayName": "device",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "keyword",
              "displayName": "keyword",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "clicks",
              "displayName": "clicks",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": false
            },
            {
              "id": "impressions",
              "displayName": "impressions",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": false
            },
            {
              "id": "position",
              "displayName": "position",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": false
            },
            {
              "id": "ctr",
              "displayName": "ctr",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": false
            },
            {
              "id": "domain",
              "displayName": "domain",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        820,
        1000
      ],
      "id": "dccf25e5-5971-424e-843d-e95b5816bde8",
      "name": "insert_keywords_ranking_by_tracked_keywords"
    },
    {
      "parameters": {
        "operation": "upsert",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "top_ranking_keywords",
          "mode": "list",
          "cachedResultName": "top_ranking_keywords"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "total_impressions": "={{ $json.total_impressions }}",
            "total_clicks": "={{ $json.total_clicks }}",
            "avg_position": "={{ $json.avg_position }}",
            "ctr_percentage": "={{ $json.ctr_percentage }}",
            "data_date": "={{ $json.data_date }}",
            "query": "={{ $json.query }}",
            "url": "={{ $json.url }}",
            "device": "={{ $json.device }}",
            "result_type": "={{ $json.result_type }}",
            "position_bucket": "={{ $json.position_bucket }}",
            "domain": "={{ $('Loop Over Items1').item.json.domain }}"
          },
          "matchingColumns": [
            "data_date",
            "query",
            "url"
          ],
          "schema": [
            {
              "id": "data_date",
              "displayName": "data_date",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "query",
              "displayName": "query",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "url",
              "displayName": "url",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "device",
              "displayName": "device",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "result_type",
              "displayName": "result_type",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "total_impressions",
              "displayName": "total_impressions",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": false
            },
            {
              "id": "total_clicks",
              "displayName": "total_clicks",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": false
            },
            {
              "id": "avg_position",
              "displayName": "avg_position",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": false
            },
            {
              "id": "ctr_percentage",
              "displayName": "ctr_percentage",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": false
            },
            {
              "id": "position_bucket",
              "displayName": "position_bucket",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "domain",
              "displayName": "domain",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        2220,
        1000
      ],
      "id": "1a2001af-41c7-4a2c-af00-6a0fefbb823d",
      "name": "insert_top_keywords"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "e3ce8bf6-cbee-4949-a338-aeb1523b646a",
              "name": "=data_date",
              "value": "={{ $now.minus({ days: 28 }).format('yyyy-MM-dd') }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        100,
        840
      ],
      "id": "fdcc21a2-4d74-40e3-960d-0bc531f13696",
      "name": "today_minus_28_d",
      "notes": "In case the pipeline has not been triggered before, then the tracking sheet is empty. If true, we will take as a starting point of today minus 7 days. "
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "e3ce8bf6-cbee-4949-a338-aeb1523b646a",
              "name": "=data_date",
              "value": "={{ $now.minus({ days: 28 }).format('yyyy-MM-dd') }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1700,
        1000
      ],
      "id": "54c2a5a1-6cf3-455a-9c66-cfe794eca549",
      "name": "today_minus_28_d_1",
      "notes": "In case the pipeline has not been triggered before, then the tracking sheet is empty. If true, we will take as a starting point of today minus 7 days. "
    },
    {
      "parameters": {
        "content": "Add all your domains and BigQuery tables here",
        "height": 220,
        "width": 160
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -100,
        340
      ],
      "id": "f27d387f-70d5-476f-8e40-b3d6c5288b0e",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "### Automation Description\nThis automation serves two main purposes:\n1. It monitors keyword rankings for all keywords in your rank tracking table\n2. It displays keywords where you already have favorable Google rankings in a separate table\n\nThe ability clearly shows whether you rank in the top 3, top 10, or top 20 for specific keywords and URLs. Additionally, it displays rankings for both mobile and desktop devices.\n\n### Required Tables\nTo use this automation, you need to create the following tables:\n\n#### 1. Top Ranking Keywords\nThis table is used to identify keyword opportunities. It helps you quickly find keywords where you already rank in the top 3, 10, or 20 positions. This information is particularly valuable for creating content that matches these search queries.\n\n```sql\nCREATE TABLE IF NOT EXISTS public.top_ranking_keywords\n(\n    data_date date NOT NULL,\n    query text COLLATE pg_catalog.\"default\" NOT NULL,\n    url text COLLATE pg_catalog.\"default\" NOT NULL,\n    device text COLLATE pg_catalog.\"default\",\n    result_type text COLLATE pg_catalog.\"default\",\n    total_impressions integer,\n    total_clicks integer,\n    avg_position double precision,\n    ctr_percentage double precision,\n    position_bucket text COLLATE pg_catalog.\"default\",\n    domain text COLLATE pg_catalog.\"default\",\n    CONSTRAINT ranking_primary_key PRIMARY KEY (data_date, query, url)\n)\n```\n\n#### 2. Tracked Keywords\nAdd the keywords you want to monitor rankings for in this table.\n\n```sql\nCREATE TABLE IF NOT EXISTS public.tracked_keywords\n(\n    domain text COLLATE pg_catalog.\"default\" NOT NULL,\n    keyword text COLLATE pg_catalog.\"default\" NOT NULL,\n    created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,\n    CONSTRAINT tracked_keywords_primary_key PRIMARY KEY (domain, keyword)\n)\n```\n\n#### 3. Rank Tracking by Keywords\nThis table exclusively tracks the rankings of keywords listed in the tracked_keywords table.\n\n```sql\nCREATE TABLE IF NOT EXISTS public.rank_tracking_by_keywords\n(\n    data_date date NOT NULL,\n    url text COLLATE pg_catalog.\"default\" NOT NULL,\n    device text COLLATE pg_catalog.\"default\",\n    keyword text COLLATE pg_catalog.\"default\" NOT NULL,\n    clicks integer,\n    impressions integer,\n    \"position\" double precision,\n    ctr double precision,\n    domain text COLLATE pg_catalog.\"default\",\n    CONSTRAINT tracked_keyword_primary_key PRIMARY KEY (data_date, url, keyword)\n)\n```",
        "height": 1200,
        "width": 3040
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -620,
        -900
      ],
      "id": "f5cc8957-a906-4a49-b3cb-7dcee72d2503",
      "name": "Sticky Note4"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -340,
        440
      ],
      "id": "92021b58-21a9-41e0-b852-a1dfcc6284f9",
      "name": "Start"
    },
    {
      "parameters": {
        "content": "Adjust this for the first run if needed",
        "height": 220,
        "width": 180
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        60,
        780
      ],
      "id": "f1b923ef-1f4e-4356-8bbb-8e5036ba36d0",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "Adjust the query if needed",
        "height": 260,
        "width": 180
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        2020,
        840
      ],
      "id": "a770b4bf-d8a0-483f-8a89-3e7cce337218",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "# Get Tracked Keywords Ranking",
        "height": 620,
        "width": 1640,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -620,
        600
      ],
      "id": "5871284a-0aa7-4d9d-a5cf-c579871ee29c",
      "name": "Sticky Note3"
    },
    {
      "parameters": {
        "content": "# Start here",
        "height": 260,
        "width": 1640
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -620,
        320
      ],
      "id": "1d8f8fd3-663a-4644-885c-30377ccb12fb",
      "name": "Sticky Note5"
    },
    {
      "parameters": {
        "content": "# Get Keyword Opportunities",
        "height": 620,
        "width": 1640,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1040,
        600
      ],
      "id": "37a05e6f-e591-4dde-a772-1046a5ffde91",
      "name": "Sticky Note6"
    }
  ],
  "pinData": {},
  "connections": {
    "Get Ranking Keywords by URL": {
      "main": [
        [
          {
            "node": "insert_keywords_ranking_by_tracked_keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Domains": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "get_date_of_last_run",
            "type": "main",
            "index": 0
          },
          {
            "node": "get_keywords_to_track",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If": {
      "main": [
        [
          {
            "node": "get_date",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "today_minus_28_d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items1": {
      "main": [
        [],
        [
          {
            "node": "get_date_of_last_run_1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If1": {
      "main": [
        [
          {
            "node": "get_date_1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "today_minus_28_d_1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Keyword Opportunities": {
      "main": [
        [
          {
            "node": "insert_top_keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_date_of_last_run": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_keywords_to_track": {
      "main": [
        [
          {
            "node": "concat_keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "merge_query_params": {
      "main": [
        [
          {
            "node": "Get Ranking Keywords by URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "concat_keywords": {
      "main": [
        [
          {
            "node": "merge_query_params",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "get_date": {
      "main": [
        [
          {
            "node": "merge_query_params",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_date_of_last_run_1": {
      "main": [
        [
          {
            "node": "If1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "merge_query_params_1": {
      "main": [
        [
          {
            "node": "Get Keyword Opportunities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_date_1": {
      "main": [
        [
          {
            "node": "merge_query_params_1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "insert_keywords_ranking_by_tracked_keywords": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "insert_top_keywords": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "today_minus_28_d": {
      "main": [
        [
          {
            "node": "merge_query_params",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "today_minus_28_d_1": {
      "main": [
        [
          {
            "node": "merge_query_params_1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Start": {
      "main": [
        [
          {
            "node": "Domains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "ea6dd1b7-3fde-41b5-aec0-ca8eff050b93",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "558d88703fb65b2d0e44613bc35916258b0f0bf983c5d4730c00c424b77ca36a"
  },
  "id": "x6AMYWZDoDaT5pD0",
  "tags": [
    {
      "createdAt": "2025-03-02T12:05:53.836Z",
      "updatedAt": "2025-03-02T12:05:53.836Z",
      "id": "utwtHTzeqUdktrxJ",
      "name": "SEO"
    },
    {
      "createdAt": "2025-03-08T08:04:57.610Z",
      "updatedAt": "2025-03-08T08:04:57.610Z",
      "id": "TMDokL1KXbN5A2PH",
      "name": "Templates"
    }
  ]
}
```


Prompt: Build a workflow for: Landing Page Analyzer

Response:
# Workflow Architecture

**Purpose**: General Automation

**Key Components**:
- Total Nodes: 15
- Node Types: n8n-nodes-base.set, @n8n/n8n-nodes-langchain.lmChatOpenAi, n8n-nodes-base.gmail, n8n-nodes-base.stickyNote, @n8n/n8n-nodes-langchain.outputParserStructured, n8n-nodes-base.code, n8n-nodes-base.httpRequest, @n8n/n8n-nodes-langchain.chainLlm, n8n-nodes-base.formTrigger, @n8n/n8n-nodes-langchain.googleGemini

**Logic Flow**:
1. **Trigger**: n8n-nodes-base.formTrigger - Initiates the workflow

## Complete Workflow JSON

```json
{
  "name": "Landing Page Analyzer",
  "nodes": [
    {
      "parameters": {
        "formTitle": "Landing Page Analyzer",
        "formFields": {
          "values": [
            {
              "fieldLabel": "URL",
              "requiredField": true
            },
            {
              "fieldLabel": "Email",
              "fieldType": "email",
              "requiredField": true
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.3,
      "position": [
        -304,
        -112
      ],
      "id": "bc0c4d73-ee5d-4dd0-8d0a-e0bfb62d020f",
      "name": "On form submission",
      "webhookId": "750d8a3a-997e-49ae-bd76-010ee665cde9"
    },
    {
      "parameters": {
        "url": "={{ $('Get Meta Data').item.json.page.screenshot }}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1168,
        -112
      ],
      "id": "013c4177-ab7b-4ae5-a5db-90ba050a074d",
      "name": "Download Image"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.firecrawl.dev/v2/scrape",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"url\": \"{{ $json.URL }}\",\n  \"onlyMainContent\": false,\n  \"parsers\": [\n    \"pdf\"\n  ],\n  \"formats\": [\n    \"markdown\",\n    {\n      \"type\": \"screenshot\",\n      \"fullPage\": true\n    }\n  ]\n} ",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -80,
        -112
      ],
      "id": "3c0939d8-89a4-4598-a106-4a3322112260",
      "name": "Crawl Site",
      "credentials": {
        "httpHeaderAuth": {
          "id": "r3zPXXitwsV4wBHf",
          "name": "Firecrawl"
        }
      }
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n  \"hero_headline\": \"Are Hidden Bottlenecks Killing Your Sales Growth?\",\n  \"hero_subheading\": \"This free 3-minute assessment pinpoints the exact leaks in your sales process.\",\n  \"value_proposition_summary\": \"We measure and improve your lead quality, follow-up speed, and closing techniques.\",\n  \"credibility_statement\": \"Created by John Doe, a sales expert with 20 years of experience who has helped scale 50+ companies.\",\n  \"cta_text\": \"Find My Sales Bottlenecks\",\n  \"cta_microcopy\": \"100% Free & Instant Results\"\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        544,
        48
      ],
      "id": "d422c0e8-7206-4d71-acaf-1cc540767cb8",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "resource": "image",
        "operation": "analyze",
        "modelId": {
          "__rl": true,
          "value": "models/gemini-2.5-pro",
          "mode": "list",
          "cachedResultName": "models/gemini-2.5-pro"
        },
        "text": "=Act as a Senior Process Engineer and world-class CRO expert, synthesizing the advice of leading conversion specialists. Your task is to conduct a comprehensive audit of a landing page using a pre-analyzed content brief and a full-page image.\n\n**[Content Brief (Data Analyst)]**\n{{ JSON.stringify($json.output, null,2) }}\n\n**[Visual Evidence]**\n[The full landing page image is provided as input]\n\n**[Expert CRO Principles & Examples for Analysis]**\nYour analysis MUST be guided by the following unified principles. Use these examples to inform your rationale.\n\n1.  **Radical Clarity:** Can a user understand the offer and benefit in under 5 seconds?\n    *   **Bad Example:** A headline like \"It's About Time.\" (Clever, but unclear what it offers).\n    *   **Good Example:** A headline like \"Generate and publish your site with AI in seconds.\" (States what you get, how, and the benefit of speed).\n\n2.  **Singular Focus & CTA:** Is there ONE primary goal and a distraction-free path to it?\n    *   **Bad Example:** A landing page with a full navigation menu (Home, About, Blog, etc.), social media links, and multiple competing CTAs.\n    *   **Good Example:** A page where the only clickable element above the fold is the primary CTA button.\n\n3.  **Cognitive Load:** Does the design prioritize function over form?\n    *   **Bad Example:** A page with an auto-playing background video, multiple elements animating on scroll, and flashy graphics that distract from the main message.\n    *   **Good Example:** A page with a clean layout, generous white space, and static images that directly support the copy.\n\n4.  **Multi-Faceted Trust:** Does the page build credibility and overcome skepticism?\n    *   **Bad Example:** A vague statement like \"Trusted by customers worldwide.\"\n    *   **Good Example:** Displaying logos of well-known clients, showing a specific testimonial with a name and photo (`\"This saved us 10 hours a week.\" - J. Doe, CEO`), or showing sheer numbers (`45,000+ projects launched`).\n\n5.  **Visual Hierarchy & CTA Isolation:** Does the design guide the eye to the most important element?\n    *   **Bad Example:** A light grey CTA button on a white background, or a page where the company logo is the largest visual element.\n    *   **Good Example:** A bright orange CTA button on a dark grey page, where orange is a unique color used ONLY for that button.\n\n6.  **Audience-Specific Complexity:** Is the level of detail appropriate for the audience and offer?\n    *   **Bad Example:** A 2,000-word landing page for a simple $5 mobile game.\n    *   **Good Example:** A detailed, multi-section landing page with downloadable case studies for a $50,000 enterprise software decision.\n\n**[Your Task]**\nSynthesize the content brief and the visual evidence to generate a final, structured JSON report. For each part, you MUST reference the expert principles above in your rationale. Follow the structure in the example below.\n\n**[Example of a Perfect JSON Output Structure]**\n{\n  \"part_1_headline_analysis\": {\n    \"obversation\": \"Based on the 'Radical Clarity' principle, the headline 'Secure Your Financial Future' is weak. It's a common cliché that lacks a specific, tangible benefit and fails to address a direct pain point for the target audience.\",\n    \"recommendation\": \"Change the headline to speak directly to a core frustration. Example: 'Stop Worrying About Retirement - Get a Clear Financial Plan in 30 Days.'\"\n  },\n  \"part_2_design_and_cognitive_load\": {\n    \"obversation\": \"The page has a clean layout which is good for 'Cognitive Load'. However, the main hero image is a generic stock photo of a happy couple, which hurts trust and authenticity. The design lacks a strong 'Visual Hierarchy' as the logo is visually larger than the headline.\",\n    \"recommendation\": \"Replace the stock photo with a professional, authentic photo of the financial advisor. Decrease the logo size by 30% and increase the headline font size to make it the dominant element.\"\n  },\n  \"part_3_offer_and_trust\": {\n    \"obversation\": \"The page fails on the 'Multi-Faceted Trust' principle. There are no client testimonials, logos, or specific credentials mentioned, making the offer feel less credible and increasing user skepticism.\",\n    \"recommendation\": \"Add a trust-building section directly below the hero. Include logos of publications the advisor has been featured in (e.g., 'As seen in Forbes') and a specific client testimonial with a name and photo.\"\n  },\n  \"part_4_conversion_path_and_cta\": {\n    \"obversation\": \"The conversion path is weak. The CTA button text 'Learn More' is vague. Based on the 'CTA Isolation' principle, its blue color does not stand out against the blue background, making it difficult to see.\",\n    \"recommendation\": \"Change the CTA text to a specific, value-oriented action like 'Book My Free Financial Review'. Change the button color to a high-contrast green that is not used elsewhere on the page.\"\n  },\n  \"part_5_summary_and_prioritized_action_plan\": {\n    \"obversation\": \"The landing page's core offer is likely valuable, but its conversion potential is severely limited by a generic headline, a lack of trust signals, and a weak, low-visibility CTA. It fails to establish credibility and clarity in the critical first 5 seconds.\",\n    \"top_3_recommendations\": [\n      \"1. Overhaul the Headline: Immediately replace the vague headline with a benefit-driven one that addresses a specific user pain point.\",\n      \"2. Redesign the CTA: Change the button text to a clear action and use a unique, high-contrast color to make it the visual anchor of the page.\",\n      \"3. Inject Social Proof: Add a testimonial and 'as seen in' logos directly below the hero section to build instant credibility.\"\n    ]\n  }\n}",
        "imageUrls": "={{ $('Get Meta Data').item.json.page.screenshot }}",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        720,
        -112
      ],
      "id": "c9a2449b-9ded-4e93-adc9-15a8856a13c0",
      "name": "Analyze an image",
      "credentials": {
        "googlePalmApi": {
          "id": "8XvIBe7gJ8Olurpj",
          "name": "Google Gemini(PaLM) Api account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// This code transforms the raw JSON string from a previous LLM node \n// into a styled, easy-to-read HTML email report.\n\n// --- Main Function to Generate HTML ---\nfunction generateEmailHtml(rawText) {\n  let analysisData;\n  try {\n    // Clean the string by removing the markdown code fences\n    const cleanJsonString = rawText.replace(/^```json\\n/, '').replace(/\\n```$/, '');\n    \n    // Parse the clean string into a JavaScript object\n    analysisData = JSON.parse(cleanJsonString);\n  } catch (error)\n  {\n    console.error(\"Error parsing JSON data:\", error);\n    // Return an error HTML if parsing fails\n    return `<h1>Error: Could not parse analysis data.</h1><p>${error.message}</p>`;\n  }\n\n  // Helper function to create a styled report section\n  const createSection = (title, obversation, recommendation) => {\n    return `\n      <div style=\"margin-bottom: 30px; padding-bottom: 20px; border-bottom: 1px solid #eeeeee;\">\n        <h3 style=\"font-size: 19px; color: #2c3e50; margin-top: 0; margin-bottom: 15px;\">${title}</h3>\n        <p style=\"margin-top: 0; margin-bottom: 12px; color: #555555; line-height: 1.6;\">\n          <strong style=\"color: #34495e; font-weight: 600;\">Observation:</strong> ${obversation}\n        </p>\n        <div style=\"background-color: #f8f9fa; border-left: 3px solid #1abc9c; padding: 12px 15px; margin-top: 10px; border-radius: 4px;\">\n          <p style=\"margin: 0; color: #555555; line-height: 1.6;\">\n            <strong style=\"color: #16a085; font-weight: 600;\">Recommendation:</strong> ${recommendation}\n          </p>\n        </div>\n      </div>\n    `;\n  };\n\n  // Construct the Full HTML Email using the parsed data\n  const html = `\n    <!DOCTYPE html>\n    <html lang=\"en\">\n    <head>\n      <meta charset=\"UTF-8\">\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n      <title>Landing Page Audit</title>\n    </head>\n    <body style=\"margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; background-color: #f4f4f4;\">\n      <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"background-color: #f4f4f4;\">\n        <tr>\n          <td align=\"center\" style=\"padding: 20px 0;\">\n            <table width=\"600\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"background-color: #ffffff; border-radius: 8px; box-shadow: 0 4px 10px rgba(0,0,0,0.1);\">\n              <tr>\n                <td align=\"center\" style=\"padding: 30px 30px 20px 30px; border-bottom: 2px solid #3498db;\">\n                  <h1 style=\"margin: 0; color: #3498db; font-size: 26px;\">Comprehensive Landing Page Audit</h1>\n                  <p style=\"margin: 5px 0 0; color: #666666; font-size: 16px;\">Analysis & Recommendations</p>\n                </td>\n              </tr>\n              <tr>\n                <td style=\"padding: 25px 30px 15px 30px;\">\n                  <p style=\"margin: 0; color: #555555; font-size: 16px; line-height: 1.6;\">\n                    Landing page analysis has been finished. The analyzed image is attached, you can find our observation and recommendations below.\n                  </p>\n                </td>\n              </tr>\n              <tr>\n                <td style=\"padding: 20px 30px 30px 30px;\">\n                  ${createSection(\n                    '1. Headline & Hook Analysis',\n                    analysisData.part_1_headline_analysis.obversation, // <-- FIXED\n                    analysisData.part_1_headline_analysis.recommendation\n                  )}\n                  \n                  ${createSection(\n                    '2. Design & Cognitive Load Analysis',\n                    analysisData.part_2_design_and_cognitive_load.obversation, // <-- FIXED\n                    analysisData.part_2_design_and_cognitive_load.recommendation\n                  )}\n\n                  ${createSection(\n                    '3. Offer & Trust Analysis',\n                    analysisData.part_3_offer_and_trust.obversation, // <-- FIXED\n                    analysisData.part_3_offer_and_trust.recommendation\n                  )}\n\n                  ${createSection(\n                    '4. Conversion Path & CTA Analysis',\n                    analysisData.part_4_conversion_path_and_cta.obversation, // <-- FIXED\n                    analysisData.part_4_conversion_path_and_cta.recommendation\n                  )}\n\n                  <!-- Final Summary Section -->\n                  <div style=\"margin-bottom: 0;\">\n                    <h3 style=\"font-size: 19px; color: #2c3e50; margin-top: 0; margin-bottom: 15px;\">5. Overall Summary & Prioritized Action Plan</h3>\n                    <p style=\"margin-top: 0; margin-bottom: 12px; color: #555555; line-height: 1.6;\">\n                      <strong style=\"color: #34495e; font-weight: 600;\">Executive Summary:</strong> ${analysisData.part_5_summary_and_prioritized_action_plan.obversation} \n                    </p>\n                    <div style=\"background-color: #f8f9fa; border-left: 3px solid #3498db; padding: 15px 15px 15px 20px; margin-top: 10px; border-radius: 4px;\">\n                      <p style=\"margin-top: 0; margin-bottom: 10px; color: #2980b9; font-weight: 600;\">\n                        Top 3 Recommendations:\n                      </p>\n                      <ol style=\"margin: 0; padding-left: 20px; color: #555555; line-height: 1.6;\">\n                        ${analysisData.part_5_summary_and_prioritized_action_plan.top_3_recommendations.map(rec => `<li style=\"margin-bottom: 10px; padding-left: 5px;\">${rec.substring(rec.indexOf('.') + 1).trim()}</li>`).join('')}\n                      </ol>\n                    </div>\n                  </div>\n                </td>\n              </tr>\n              <tr>\n                <td align=\"center\" style=\"padding: 20px 30px; background-color: #f8f9fa; border-top: 1px solid #eeeeee; border-radius: 0 0 8px 8px;\">\n                  <p style=\"margin: 0; color: #999999; font-size: 12px;\">This is an automated analysis report.</p>\n                </td>\n              </tr>\n            </table>\n          </td>\n        </tr>\n      </table>\n    </body>\n    </html>\n  `;\n\n  return html;\n}\n\n// --- n8n Execution Logic ---\ntry {\n  // Access the raw text from the input of the n8n node\n  const rawInputText = $input.first().json.content.parts[0].text;\n  \n  // Generate the complete HTML string\n  const finalHtml = generateEmailHtml(rawInputText);\n  \n  // Return the HTML in a structured way for the next node\n  return {\n    json: {\n      emailHtml: finalHtml\n    }\n  };\n} catch (error) {\n  // Return an error object if the input path is invalid\n  return {\n    json: {\n      error: \"Failed to access input data. Please check the input path.\",\n      details: error.message\n    }\n  };\n}"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        944,
        -112
      ],
      "id": "084f376c-9e4e-4cfd-8ea3-d735d17de1f5",
      "name": "Generate HTML"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Act as a marketing copy analyst. Your task is to read the provided landing page text and extract the key marketing components into a structured JSON format.\n\n**[Provided Text]**\n- Page Title: \"{{$json.page.title }}\"\n- Meta Description: \"{{ $json.page.description }}\"\n- Main Content: \"{{ $json.page.content }}\"\n\n**[Your Task]**\nAnalyze the Main Content and identify the following elements. If an element is not found, return an empty string \"\".\n1.  `hero_headline`: The main headline at the top of the page.\n2.  `hero_subheading`: The subheading directly under the main headline.\n3.  `value_proposition_summary`: A summary of the section explaining the benefits of the assessment.\n4.  `credibility_statement`: A summary of the section building trust (e.g., creator's bio, research mentioned).\n5.  `cta_text`: The text on the primary call-to-action button.\n6.  `cta_microcopy`: Any supporting text immediately near the CTA button (e.g., \"Takes 3 minutes\").\n\nReturn ONLY the JSON object.",
        "hasOutputParser": true,
        "batching": {}
      },
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.7,
      "position": [
        368,
        -112
      ],
      "id": "730e6024-127c-48d3-aa06-9155e6b2731d",
      "name": "Analyze Page Content"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "8137accd-97ed-463c-8eca-e2585f44d355",
              "name": "page.title",
              "value": "={{ $json.data.metadata.title }}",
              "type": "string"
            },
            {
              "id": "a4ca9b7c-f122-4a51-b7cc-c83c24fdfa2a",
              "name": "page.content",
              "value": "={{ $json.data.markdown }}",
              "type": "string"
            },
            {
              "id": "87d98606-c982-4b6d-a949-ebbf29fda5a3",
              "name": "page.language",
              "value": "={{ $json.data.metadata.language }}",
              "type": "string"
            },
            {
              "id": "9f400108-6985-441b-a2b2-738e9260a4af",
              "name": "page.description",
              "value": "={{ $json.data.metadata.description }}",
              "type": "string"
            },
            {
              "id": "526774ae-2347-407a-bb87-f92e4bd28fed",
              "name": "page.screenshot",
              "value": "={{ $json.data.screenshot }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        144,
        -112
      ],
      "id": "52937fbf-8341-4c51-99fa-157970c79c60",
      "name": "Get Meta Data"
    },
    {
      "parameters": {
        "sendTo": "={{ $('On form submission').item.json.Email }}",
        "subject": "=Landing Page Analysis For  {{ $('On form submission').item.json.URL }}",
        "message": "={{ $('Generate HTML').item.json.emailHtml }}",
        "options": {
          "appendAttribution": false,
          "attachmentsUi": {
            "attachmentsBinary": [
              {
                "property": "=data"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1392,
        -112
      ],
      "id": "7b162a7f-7d5c-4a52-8daf-e326d1b7e5be",
      "name": "Send Report",
      "webhookId": "a318cd20-bf1a-4e8d-b329-8669758c50f8",
      "credentials": {
        "gmailOAuth2": {
          "id": "S5zG40aAsfQKXkT0",
          "name": "Gmail account"
        }
      }
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        352,
        64
      ],
      "id": "05fea720-79bc-4e49-b5c7-c247b0a914f5",
      "name": "gpt-4.1-mini",
      "credentials": {
        "openAiApi": {
          "id": "RAj3VxCHt0rIwBTk",
          "name": "OpenAI"
        }
      }
    },
    {
      "parameters": {
        "content": "# Workflow created by [Marvomatic](https://marvomatic.com/)\n- [AI SEO Society (Free)](https://www.skool.com/ai-automation-community)\n- [AI SEO Society](https://www.skool.com/the-ai-seo-society-free-7625)\n- [Contact](https://marvomatic.com/contact/)",
        "height": 144,
        "width": 1936,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -352,
        -336
      ],
      "id": "693fe15a-14cb-4a71-a383-adc431eeaa0e",
      "name": "Sticky Note6"
    },
    {
      "parameters": {
        "content": "## Scrape URL",
        "height": 352,
        "width": 448,
        "color": 6
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -160,
        -176
      ],
      "id": "0940e7b7-c580-4ccc-acc1-6be2c7a5a235",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## Analyze Content & Screenshot",
        "height": 352,
        "width": 560,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        312,
        -176
      ],
      "id": "9e69a40d-8c8d-40ee-ab86-4e077b9d6bf6",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "## Generate & Send Email",
        "height": 352,
        "width": 688,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        896,
        -176
      ],
      "id": "730b6ccb-f703-46ab-bcad-cfaccbb4f5ef",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "## Get Data",
        "height": 352,
        "width": 176
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -352,
        -176
      ],
      "id": "175a0ec7-6921-464a-bd01-300ffd0ff016",
      "name": "Sticky Note3"
    }
  ],
  "pinData": {},
  "connections": {
    "On form submission": {
      "main": [
        [
          {
            "node": "Crawl Site",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Image": {
      "main": [
        [
          {
            "node": "Send Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Crawl Site": {
      "main": [
        [
          {
            "node": "Get Meta Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Analyze Page Content",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Analyze an image": {
      "main": [
        [
          {
            "node": "Generate HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate HTML": {
      "main": [
        [
          {
            "node": "Download Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Page Content": {
      "main": [
        [
          {
            "node": "Analyze an image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Meta Data": {
      "main": [
        [
          {
            "node": "Analyze Page Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "gpt-4.1-mini": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze Page Content",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "7d5eb14a-7480-4435-b0dc-22ac157845be",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "558d88703fb65b2d0e44613bc35916258b0f0bf983c5d4730c00c424b77ca36a"
  },
  "id": "VpoGZ7jDRWBJJQU0",
  "tags": []
}
```