This workflow corresponds to n8n.io template #17698 — we link there as the canonical source.
This workflow follows the Apifyn8N Nodes Apify → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Track competitor ads from the Google Ads Transparency Center in Google Sheets",
"nodes": [
{
"id": "b7e2d914-0001-4c01-9001-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": "b7e2d914-0002-4c02-9002-000000000002",
"name": "Set the competitors to watch",
"type": "n8n-nodes-base.set",
"position": [
260,
460
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b7e2d914-0010-4c10-9010-+1234567890",
"name": "advertiserIds",
"type": "array",
"value": "[\"AR0161401435+1234567890\"]"
},
{
"id": "b7e2d914-0011-4c11-9011-+1234567890",
"name": "maxAdsPerAdvertiser",
"type": "number",
"value": "20"
},
{
"id": "b7e2d914-0012-4c12-9012-+1234567890",
"name": "region",
"type": "string",
"value": ""
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b7e2d914-0003-4c03-9003-000000000003",
"name": "Fetch each advertiser's ads",
"type": "@apify/n8n-nodes-apify.apify",
"position": [
520,
460
],
"parameters": {
"memory": 128,
"actorId": "johnvc~google-ads-transparency-api",
"resource": "Actors",
"operation": "Run actor and get dataset",
"customBody": "={{ JSON.stringify({ advertiserIds: $json.advertiserIds, maxResultsPerAdvertiser: $json.maxAdsPerAdvertiser, region: $json.region }) }}"
},
"typeVersion": 1
},
{
"id": "b7e2d914-0004-4c04-9004-000000000004",
"name": "Keep rows that are real ads",
"type": "n8n-nodes-base.filter",
"position": [
780,
460
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "b7e2d914-0041-4c41-9041-+1234567890",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.result_type }}",
"rightValue": "ad"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "b7e2d914-0005-4c05-9005-000000000005",
"name": "Shape ad rows for the sheet",
"type": "n8n-nodes-base.code",
"position": [
1040,
460
],
"parameters": {
"jsCode": "// One row per competitor ad, with the dates made readable and the\n// long-running creatives flagged. A creative that has been live for months\n// is one the competitor keeps paying for, which is the useful signal here.\nconst weekOf = $now.toFormat('yyyy-MM-dd');\nconst asDate = (unix) =>\n typeof unix === 'number' && unix > 0\n ? new Date(unix * 1000).toISOString().slice(0, 10)\n : '';\n\nreturn $input.all().map((item) => {\n const ad = item.json;\n const days = typeof ad.total_days_shown === 'number' ? ad.total_days_shown : '';\n return {\n json: {\n 'Week of': weekOf,\n Advertiser: ad.advertiser || '',\n 'Ad format': ad.format || '',\n 'First shown': asDate(ad.first_shown),\n 'Days running': days,\n 'Long runner': days !== '' && days >= 90 ? 'YES' : '',\n 'Creative link': ad.details_link || '',\n 'Creative ID': ad.ad_creative_id || '',\n 'Advertiser ID': ad.advertiser_id || '',\n },\n };\n});\n"
},
"typeVersion": 2
},
{
"id": "b7e2d914-0006-4c06-9006-000000000006",
"name": "Append this week's ads",
"type": "n8n-nodes-base.googleSheets",
"position": [
1300,
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": "b7e2d914-0090-4c90-9090-000000000090",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-620,
40
],
"parameters": {
"width": 520,
"height": 1140,
"content": "## Track competitor ads from the Google Ads Transparency Center in Google Sheets\n\nNo ad spy subscription and no agency retainer. Every week this workflow reads the Google Ads Transparency Center for the advertisers you list and appends one row per ad to your sheet: advertiser, format, when it first ran, how many days it has been running, and a link to the creative itself.\n\nThe column that earns its keep is Days running. Anyone can see what a competitor is advertising today. Seeing that one creative has been live for 543 days tells you which message they keep paying for, which is the one worth studying.\n\n**Who's it for**\nPerformance marketers sizing up a competitor before a launch, agencies building a pitch deck, and founders who want to know what the funded competitor is actually saying.\n\n**How it works**\n1. A schedule trigger fires once a week\n2. One Set node holds the advertiser IDs you want to watch\n3. The Apify node pulls each advertiser's live ad library\n4. A Code node turns the timestamps into dates and flags the long runners\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. Open adstransparency.google.com, search each competitor, and copy the AR... code out of the URL into the config node. The example ships with one advertiser; add the rest of your set and the sheet becomes a side by side.\n\n**Good to know**\nAbout a third of a cent per ad, so three competitors at 20 ads each is roughly 20 cents a week.\nThe Transparency Center only lists ads an advertiser is running now, so every row is live. It does not publish spend or impressions.\nActor: https://apify.com/johnvc/google-ads-transparency-api?fpr=9n7kx3&fp_sid=n8n"
},
"typeVersion": 1
},
{
"id": "b7e2d914-0091-4c91-9091-000000000091",
"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 while you test."
},
"typeVersion": 1
},
{
"id": "b7e2d914-0092-4c92-9092-000000000092",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
220,
60
],
"parameters": {
"color": 7,
"width": 240,
"height": 240,
"content": "### 2. Your input\nThe advertiser IDs you want to watch, and how many ads to pull for each. This is the only node you edit."
},
"typeVersion": 1
},
{
"id": "b7e2d914-0093-4c93-9093-000000000093",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
480,
60
],
"parameters": {
"color": 7,
"width": 240,
"height": 240,
"content": "### 3. Fetch\nReads each advertiser's library from the Google Ads Transparency Center. Add your Apify credential here."
},
"typeVersion": 1
},
{
"id": "b7e2d914-0094-4c94-9094-000000000094",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
740,
60
],
"parameters": {
"color": 7,
"width": 240,
"height": 240,
"content": "### 4. Clean\nDrops any advertiser that returned an error, so only real ads reach the sheet."
},
"typeVersion": 1
},
{
"id": "b7e2d914-0095-4c95-9095-000000000095",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1000,
60
],
"parameters": {
"color": 7,
"width": 240,
"height": 240,
"content": "### 5. Shape\nTurns the timestamps into readable dates and flags creatives running 90 days or more."
},
"typeVersion": 1
},
{
"id": "b7e2d914-0096-4c96-9096-000000000096",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1260,
60
],
"parameters": {
"color": 7,
"width": 240,
"height": 240,
"content": "### 6. Deliver\nPick your spreadsheet and tab. Columns map automatically."
},
"typeVersion": 1
},
{
"id": "b7e2d914-0080-4c80-9080-000000000080",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
220,
760
],
"parameters": {
"color": 7,
"width": 400,
"height": 240,
"content": "### Where do I find an advertiser ID?\nGo to adstransparency.google.com, search the company, and open its page. The URL contains an `AR...` code. That code is the advertiser ID. One company can have several, one per legal entity."
},
"typeVersion": 1
},
{
"id": "b7e2d914-0081-4c81-9081-000000000081",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
660,
760
],
"parameters": {
"color": 7,
"width": 400,
"height": 240,
"content": "### Self-hosting n8n?\nThere is also a dedicated community node for this actor: `n8n-nodes-google-ads-transparency-api` on npm."
},
"typeVersion": 1
}
],
"settings": {
"executionOrder": "v1"
},
"connections": {
"Every Monday morning": {
"main": [
[
{
"node": "Set the competitors to watch",
"type": "main",
"index": 0
}
]
]
},
"Fetch each advertiser's ads": {
"main": [
[
{
"node": "Keep rows that are real ads",
"type": "main",
"index": 0
}
]
]
},
"Keep rows that are real ads": {
"main": [
[
{
"node": "Shape ad rows for the sheet",
"type": "main",
"index": 0
}
]
]
},
"Shape ad rows for the sheet": {
"main": [
[
{
"node": "Append this week's ads",
"type": "main",
"index": 0
}
]
]
},
"Set the competitors to watch": {
"main": [
[
{
"node": "Fetch each advertiser's ads",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
No ad spy subscription and no agency retainer. Every week this reads the Google Ads Transparency Center for the advertisers you list and appends one row per ad to Google Sheets: advertiser, format, when it first ran, how long it has run, and a link to the creative. Runs every…
Source: https://n8n.io/workflows/17698/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
No rank tracker subscription and no SERP API key. This template checks where your business ranks in Google's local results for the keywords you choose, every week, and appends one row per listing to G
No Firecrawl API key and no OpenAI key. This template checks every week whether any member of Congress disclosed a trade in the stocks you follow, and appends one row per transaction to Google Sheets:
No Google Business Profile connection and no SerpApi or Bright Data account. This template runs weekly review tracking across the whole Google local pack for your search term, appending one row per bu
No IP watch service and no per-seat subscription. Every week this searches Google Patents for the technologies you follow and appends one row per patent to Google Sheets: title, assignee, inventor, pu
This workflow runs every Monday morning, searches Google Shopping for a list of products using Apify, summarizes credible weekly pricing metrics per product, and appends the results to a Google Sheets