{
  "name": "Track Google local pack rankings in Google Sheets with Apify",
  "nodes": [
    {
      "id": "7c3d2b5e-0001-4c01-c001-000000000001",
      "name": "Every Monday morning",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        460
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "7c3d2b5e-0007-4c07-c007-000000000007",
      "name": "Set your keywords and location",
      "type": "n8n-nodes-base.set",
      "position": [
        260,
        460
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "7c3d2b5e-0002-4c02-c+1234567890",
              "name": "keywords",
              "type": "array",
              "value": "[\"coffee shop\", \"best coffee austin\", \"espresso bar\"]"
            },
            {
              "id": "7c3d2b5e-0003-4c03-c+1234567890",
              "name": "location",
              "type": "string",
              "value": "Austin, Texas, United States"
            },
            {
              "id": "7c3d2b5e-0004-4c04-c+1234567890",
              "name": "yourBusinessName",
              "type": "string",
              "value": "Houndstooth Coffee"
            },
            {
              "id": "7c3d2b5e-0005-4c05-c+1234567890",
              "name": "googleDomain",
              "type": "string",
              "value": "google.com"
            },
            {
              "id": "7c3d2b5e-0006-4c06-c+1234567890",
              "name": "country",
              "type": "string",
              "value": "us"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7c3d2b5e-0008-4c08-c008-000000000008",
      "name": "One search per keyword",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        520,
        460
      ],
      "parameters": {
        "include": "allOtherFields",
        "options": {},
        "fieldToSplitOut": "keywords"
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-0009-4c09-c009-000000000009",
      "name": "Search the Google local pack",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        780,
        460
      ],
      "parameters": {
        "memory": 4096,
        "actorId": "johnvc~google-local-api",
        "resource": "Actors",
        "operation": "Run actor and get dataset",
        "customBody": "={{ JSON.stringify({ q: $json.keywords, location: $json.location, google_domain: $json.googleDomain, gl: $json.country, hl: 'en', max_pages: 1 }) }}"
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-000b-4c0b-c00b-00000000000b",
      "name": "Keep searches that returned a pack",
      "type": "n8n-nodes-base.filter",
      "position": [
        1040,
        460
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7c3d2b5e-000a-4c0a-c00a-+1234567890a",
              "operator": {
                "type": "array",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.local_results }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7c3d2b5e-000c-4c0c-c00c-00000000000c",
      "name": "One row per listing",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1300,
        460
      ],
      "parameters": {
        "include": "selectedOtherFields",
        "options": {},
        "fieldToSplitOut": "local_results",
        "fieldsToInclude": "search_parameters"
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-0016-4c16-c016-000000000016",
      "name": "Pick fields for the sheet",
      "type": "n8n-nodes-base.set",
      "position": [
        1560,
        460
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "7c3d2b5e-000d-4c0d-c00d-+1234567890d",
              "name": "Date",
              "type": "string",
              "value": "={{ $now.format('yyyy-MM-dd') }}"
            },
            {
              "id": "7c3d2b5e-000e-4c0e-c00e-+1234567890e",
              "name": "Keyword",
              "type": "string",
              "value": "={{ $json.search_parameters.q }}"
            },
            {
              "id": "7c3d2b5e-000f-4c0f-c00f-+1234567890f",
              "name": "Position",
              "type": "string",
              "value": "={{ $json.local_results.position }}"
            },
            {
              "id": "7c3d2b5e-0010-4c10-c010-+1234567890",
              "name": "Business",
              "type": "string",
              "value": "={{ $json.local_results.title }}"
            },
            {
              "id": "7c3d2b5e-0011-4c11-c011-+1234567890",
              "name": "Is your business",
              "type": "string",
              "value": "={{ ($json.local_results.title || '').toLowerCase().includes($('Set your keywords and location').first().json.yourBusinessName.toLowerCase()) ? 'YES' : '' }}"
            },
            {
              "id": "7c3d2b5e-0012-4c12-c012-+1234567890",
              "name": "Category",
              "type": "string",
              "value": "={{ $json.local_results.type }}"
            },
            {
              "id": "7c3d2b5e-0013-4c13-c013-+1234567890",
              "name": "Rating",
              "type": "string",
              "value": "={{ $json.local_results.rating }}"
            },
            {
              "id": "7c3d2b5e-0014-4c14-c014-+1234567890",
              "name": "Reviews",
              "type": "string",
              "value": "={{ $json.local_results.reviews }}"
            },
            {
              "id": "7c3d2b5e-0015-4c15-c015-+1234567890",
              "name": "Address",
              "type": "string",
              "value": "={{ $json.local_results.address }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7c3d2b5e-0017-4c17-c017-000000000017",
      "name": "Append rankings to sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1820,
        460
      ],
      "parameters": {
        "columns": {
          "value": {},
          "mappingMode": "autoMapInputData",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "7c3d2b5e-0018-4c18-c018-000000000018",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -620,
        40
      ],
      "parameters": {
        "width": 520,
        "height": 1080,
        "content": "## Track Google local pack rankings in Google Sheets with Apify\n\nNo rank tracker subscription and no SERP API key. Every week this workflow checks where your business sits in Google's local results for the keywords you care about, and appends one row per listing to your sheet: position, business name, category, rating, review count, and address, with your own listing flagged YES.\n\nBecause it logs the whole pack and not just your rank, the sheet doubles as a competitor watch: you can see exactly who moved above you and what their review count looks like.\n\n**Who's it for**\nLocal SEO consultants tracking client rankings, multi-location marketers, and owners who want to know they slipped from position 3 to 8 before the phone stops ringing.\n\n**How it works**\n1. A schedule trigger fires once a week\n2. One Set node holds your keywords, city, and business name\n3. The Apify node runs one local search per keyword\n4. Every listing that came back becomes a row, with yours marked\n\n**Setup**\n1. Create a free Apify account and add your API token to the Apify credential\n2. Connect your Google account in the Sheets node and pick a spreadsheet\n3. Replace the example keywords, location, and business name, then run once to test\n\n**Good to know**\nAbout 2 cents per keyword per run. Five keywords checked weekly costs roughly 11 cents a week.\nActor: https://apify.com/johnvc/google-local-api?fpr=9n7kx3&fp_sid=n8n"
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-0019-4c19-c019-000000000019",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 1. Schedule\nRuns every Monday morning. Change the cadence or swap in a manual trigger."
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-001a-4c1a-c01a-00000000001a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        220,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 2. Your input\nKeywords, city, and your business name. This is the only node you edit."
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-001b-4c1b-c01b-00000000001b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        480,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 3. Fan out\nTurns your keyword list into one search each."
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-001c-4c1c-c01c-00000000001c",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        740,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 4. Search\nRuns the Google Local API actor. Add your Apify credential here."
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-001d-4c1d-c01d-00000000001d",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1000,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 5. Clean\nSkips any keyword that returned no local results."
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-001e-4c1e-c01e-00000000001e",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1260,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 6. Unpack\nSplits the pack into one item per business listing."
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-001f-4c1f-c01f-00000000001f",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1520,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 7. Shape\nChoose your sheet columns. Your own listing is flagged YES."
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-0020-4c20-c020-000000000020",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1780,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 8. Deliver\nPick your spreadsheet and tab. Columns map automatically."
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-0021-4c21-c021-000000000021",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        220,
        760
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 220,
        "content": "### Tracking another country?\nChange googleDomain and country together in the config node, for example google.co.uk and uk."
      },
      "typeVersion": 1
    },
    {
      "id": "7c3d2b5e-0022-4c22-c022-000000000022",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        760
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 220,
        "content": "### Self-hosting n8n?\nThere is also a dedicated community node for this actor: `n8n-nodes-google-local-api` on npm."
      },
      "typeVersion": 1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "One row per listing": {
      "main": [
        [
          {
            "node": "Pick fields for the sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every Monday morning": {
      "main": [
        [
          {
            "node": "Set your keywords and location",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "One search per keyword": {
      "main": [
        [
          {
            "node": "Search the Google local pack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pick fields for the sheet": {
      "main": [
        [
          {
            "node": "Append rankings to sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search the Google local pack": {
      "main": [
        [
          {
            "node": "Keep searches that returned a pack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set your keywords and location": {
      "main": [
        [
          {
            "node": "One search per keyword",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keep searches that returned a pack": {
      "main": [
        [
          {
            "node": "One row per listing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}