This workflow corresponds to n8n.io template #17453 — we link there as the canonical source.
This workflow follows the Gmail → HTTP Request 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 →
{
"id": "lJ55B9JA2gEldRw9",
"meta": {
"builderVariant": "mcp",
"aiBuilderAssisted": true
},
"name": "Send Weekly Search Console Report",
"tags": [],
"nodes": [
{
"id": "244b17ae-abca-4b2c-acc1-53f5cd5549ac",
"name": "Weekly Mon 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-80,
416
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtDay": [
1
],
"triggerAtHour": 8
}
]
}
},
"typeVersion": 1.3
},
{
"id": "4cb3bdc1-75be-4bc9-bd70-c0ab2604d1c0",
"name": "Build Date Ranges",
"type": "n8n-nodes-base.set",
"notes": "Two 7-day windows ending 3 days ago (Search Console finalizes data with a ~2-3 day lag).",
"position": [
192,
416
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f0",
"name": "siteUrl",
"type": "string",
"value": "https://pocketfmmodapk.com/"
},
{
"id": "f1",
"name": "currentStart",
"type": "string",
"value": "={{ $today.minus({ days: 9 }).toFormat(\"yyyy-MM-dd\") }}"
},
{
"id": "f2",
"name": "currentEnd",
"type": "string",
"value": "={{ $today.minus({ days: 3 }).toFormat(\"yyyy-MM-dd\") }}"
},
{
"id": "f3",
"name": "previousStart",
"type": "string",
"value": "={{ $today.minus({ days: 16 }).toFormat(\"yyyy-MM-dd\") }}"
},
{
"id": "f4",
"name": "previousEnd",
"type": "string",
"value": "={{ $today.minus({ days: 10 }).toFormat(\"yyyy-MM-dd\") }}"
},
{
"id": "f5",
"name": "currentLabel",
"type": "string",
"value": "={{ $today.minus({ days: 9 }).toFormat(\"MMM d\") }} to {{ $today.minus({ days: 3 }).toFormat(\"MMM d, yyyy\") }}"
},
{
"id": "f6",
"name": "previousLabel",
"type": "string",
"value": "={{ $today.minus({ days: 16 }).toFormat(\"MMM d\") }} to {{ $today.minus({ days: 10 }).toFormat(\"MMM d, yyyy\") }}"
},
{
"id": "f7",
"name": "generatedAt",
"type": "string",
"value": "={{ $now.toFormat(\"MMMM d, yyyy\") }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "da0192d6-9451-45b2-b14b-bdf587420f5b",
"name": "Totals This Week",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"maxTries": 3,
"position": [
448,
416
],
"parameters": {
"url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($('Build Date Ranges').item.json.siteUrl) }}/searchAnalytics/query",
"method": "POST",
"options": {},
"jsonBody": "={ \"startDate\": \"{{ $(\"Build Date Ranges\").item.json.currentStart }}\", \"endDate\": \"{{ $(\"Build Date Ranges\").item.json.currentEnd }}\", \"dataState\": \"final\" }",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleApi"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.4,
"waitBetweenTries": 5000
},
{
"id": "67c42fea-000a-4c5c-9f6f-34a51b4330a4",
"name": "Error Alert",
"type": "n8n-nodes-base.gmail",
"position": [
1840,
416
],
"parameters": {
"sendTo": "user@example.com",
"message": "=<div style=\"font-family:-apple-system,Segoe UI,Roboto,Arial,sans-serif;max-width:560px;\"><h2 style=\"color:#b91c1c;margin:0 0 8px;\">Weekly Search Console report failed</h2><p style=\"color:#374151;\">Workflow <b>{{ $workflow.name }}</b> errored while pulling data from Google Search Console, so no report was sent this run.</p><p style=\"color:#374151;\"><b>Error:</b> {{ $json.error?.message || $json.message || \"Unknown error\" }}</p><p style=\"color:#6b7280;font-size:13px;\"><b>Execution ID:</b> {{ $execution.id }}</p></div>",
"options": {
"appendAttribution": false
},
"subject": "=GSC Weekly Report FAILED - {{ $now.toFormat(\"MMM d, yyyy\") }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "c5149bbd-921b-42c3-a827-c76d33acc431",
"name": "Totals Last Week",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"maxTries": 3,
"position": [
672,
336
],
"parameters": {
"url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($('Build Date Ranges').item.json.siteUrl) }}/searchAnalytics/query",
"method": "POST",
"options": {},
"jsonBody": "={ \"startDate\": \"{{ $(\"Build Date Ranges\").item.json.previousStart }}\", \"endDate\": \"{{ $(\"Build Date Ranges\").item.json.previousEnd }}\", \"dataState\": \"final\" }",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleApi"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.4,
"waitBetweenTries": 5000
},
{
"id": "ad1c2264-0baa-4c82-b70b-9b7c61c9fafc",
"name": "Queries This Week",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"maxTries": 3,
"position": [
896,
272
],
"parameters": {
"url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($('Build Date Ranges').item.json.siteUrl) }}/searchAnalytics/query",
"method": "POST",
"options": {},
"jsonBody": "={ \"startDate\": \"{{ $(\"Build Date Ranges\").item.json.currentStart }}\", \"endDate\": \"{{ $(\"Build Date Ranges\").item.json.currentEnd }}\", \"dimensions\": [\"query\"], \"rowLimit\": 10, \"dataState\": \"final\" }",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleApi"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.4,
"waitBetweenTries": 5000
},
{
"id": "e385ae45-58ca-488e-8c21-d391fa1126c1",
"name": "Queries Last Week",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"maxTries": 3,
"position": [
1120,
192
],
"parameters": {
"url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($('Build Date Ranges').item.json.siteUrl) }}/searchAnalytics/query",
"method": "POST",
"options": {},
"jsonBody": "={ \"startDate\": \"{{ $(\"Build Date Ranges\").item.json.previousStart }}\", \"endDate\": \"{{ $(\"Build Date Ranges\").item.json.previousEnd }}\", \"dimensions\": [\"query\"], \"rowLimit\": 250, \"dataState\": \"final\" }",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleApi"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.4,
"waitBetweenTries": 5000
},
{
"id": "6609c7ba-bc99-43a1-8715-b076267fcee3",
"name": "Pages This Week",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"maxTries": 3,
"position": [
1344,
128
],
"parameters": {
"url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($('Build Date Ranges').item.json.siteUrl) }}/searchAnalytics/query",
"method": "POST",
"options": {},
"jsonBody": "={ \"startDate\": \"{{ $(\"Build Date Ranges\").item.json.currentStart }}\", \"endDate\": \"{{ $(\"Build Date Ranges\").item.json.currentEnd }}\", \"dimensions\": [\"page\"], \"rowLimit\": 10, \"dataState\": \"final\" }",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleApi"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.4,
"waitBetweenTries": 5000
},
{
"id": "5ff3dce6-7f24-4b57-8d4d-45b0c7781831",
"name": "Pages Last Week",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"maxTries": 3,
"position": [
1568,
48
],
"parameters": {
"url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($('Build Date Ranges').item.json.siteUrl) }}/searchAnalytics/query",
"method": "POST",
"options": {},
"jsonBody": "={ \"startDate\": \"{{ $(\"Build Date Ranges\").item.json.previousStart }}\", \"endDate\": \"{{ $(\"Build Date Ranges\").item.json.previousEnd }}\", \"dimensions\": [\"page\"], \"rowLimit\": 250, \"dataState\": \"final\" }",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleApi"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.4,
"waitBetweenTries": 5000
},
{
"id": "e5519332-5a18-44fa-8daa-932927c2ecca",
"name": "Build Report",
"type": "n8n-nodes-base.code",
"position": [
1792,
0
],
"parameters": {
"jsCode": "const d = $('Build Date Ranges').first().json;\nconst rowsOf = (name) => { const r = $(name).first().json; return (r && r.rows) ? r.rows : []; };\nconst totalsOf = (name) => rowsOf(name)[0] || {};\nconst num = (v) => (typeof v === 'number' && isFinite(v)) ? v : 0;\n\nconst curT = totalsOf('Totals This Week');\nconst prevT = totalsOf('Totals Last Week');\nconst curQ = rowsOf('Queries This Week');\nconst curP = rowsOf('Pages This Week');\nconst mapBy = (rows) => { const m = {}; rows.forEach((r) => { const k = (r.keys && r.keys[0] !== undefined) ? r.keys[0] : ''; m[k] = r; }); return m; };\nconst prevQMap = mapBy(rowsOf('Queries Last Week'));\nconst prevPMap = mapBy(rowsOf('Pages Last Week'));\n\nconst fmtInt = (x) => Math.round(x).toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\nconst fmtCtr = (x) => (x * 100).toFixed(1) + '%';\nconst fmtPos = (x) => x.toFixed(1);\n\nconst GREEN = '#16a34a'; const RED = '#dc2626'; const GRAY = '#94a3b8';\nconst chip = (raw, higherBetter, fmt) => {\n const rounded = Math.round(raw * 100) / 100;\n if (Math.abs(rounded) < 0.05) return '';\n const better = higherBetter ? rounded > 0 : rounded < 0;\n const color = better ? GREEN : RED;\n const arrow = better ? '\\u25B2' : '\\u25BC';\n return '<div style=\"font-size:10px;font-weight:600;color:' + color + ';\">' + arrow + fmt(Math.abs(rounded)) + '</div>';\n};\nconst newChip = '<div style=\"font-size:10px;font-weight:600;color:' + GRAY + ';\">new</div>';\nconst mTd = (valStr, chipHtml, primary) => {\n const vStyle = primary ? 'font-size:14px;font-weight:600;color:#0f172a;' : 'font-size:13px;color:#475569;';\n return '<td style=\"padding:10px 12px;text-align:right;border-bottom:1px solid #f2f4f8;\"><div style=\"' + vStyle + '\">' + valStr + '</div>' + (chipHtml || '') + '</td>';\n};\nconst dataRow = (label, cur, prev) => {\n const c = { clicks: num(cur.clicks), impr: num(cur.impressions), ctr: num(cur.ctr), pos: num(cur.position) };\n let cc, ci, cr, cp;\n if (prev) {\n const p = { clicks: num(prev.clicks), impr: num(prev.impressions), ctr: num(prev.ctr), pos: num(prev.position) };\n cc = chip(c.clicks - p.clicks, true, (i) => Math.round(i).toString());\n ci = chip(c.impr - p.impr, true, (i) => Math.round(i).toString());\n cr = chip((c.ctr - p.ctr) * 100, true, (i) => i.toFixed(1));\n cp = chip(c.pos - p.pos, false, (i) => i.toFixed(1));\n } else { cc = newChip; ci = ''; cr = ''; cp = ''; }\n return '<tr>' +\n '<td style=\"padding:10px 12px;font-size:13px;color:#334155;border-bottom:1px solid #f2f4f8;\">' + label + '</td>' +\n mTd(fmtInt(c.clicks), cc, true) + mTd(fmtInt(c.impr), ci, false) + mTd(fmtCtr(c.ctr), cr, false) + mTd(fmtPos(c.pos), cp, false) +\n '</tr>';\n};\nconst stripUrl = (u) => ((u || '').replace(/^https?:\\/\\/[^/]+/, '') || '/');\nconst emptyRow = '<tr><td colspan=\"5\" style=\"padding:14px;text-align:center;color:#94a3b8;font-size:13px;\">No data for this period.</td></tr>';\nconst qRows = curQ.length ? curQ.map((r) => { const k = (r.keys && r.keys[0]) ? r.keys[0] : '(unknown)'; return dataRow(k, r, prevQMap[k]); }).join('') : emptyRow;\nconst pRows = curP.length ? curP.map((r) => { const k = (r.keys && r.keys[0]) ? r.keys[0] : ''; return dataRow(stripUrl(k), r, prevPMap[k]); }).join('') : emptyRow;\n\nconst kpiPill = (cur, prev, higherBetter, kind) => {\n const raw = kind === 'pct' ? (prev === 0 ? (cur === 0 ? 0 : 100) : ((cur - prev) / prev) * 100) : (cur - prev);\n const rounded = Math.round(raw * 10) / 10;\n const flat = Math.abs(rounded) < 0.05;\n const better = higherBetter ? raw > 0 : raw < 0;\n const color = flat ? '#64748b' : (better ? '#15803d' : '#b91c1c');\n const bg = flat ? '#f1f5f9' : (better ? '#dcfce7' : '#fee2e2');\n const arrow = flat ? '' : (better ? '\\u25B2 ' : '\\u25BC ');\n const mag = kind === 'pct' ? Math.abs(rounded).toFixed(1) + '%' : Math.abs(rounded).toFixed(1);\n return '<span style=\"font-size:11px;font-weight:600;color:' + color + ';background:' + bg + ';border-radius:999px;padding:2px 9px;\">' + arrow + mag + '</span>';\n};\nconst kpiCard = (label, valStr, pill, fromStr) =>\n '<td style=\"width:25%;vertical-align:top;padding:6px;\">' +\n '<div style=\"background:#f8fafc;border:1px solid #eef1f5;border-radius:12px;padding:16px 12px;text-align:center;\">' +\n '<div style=\"font-size:11px;color:#94a3b8;text-transform:uppercase;letter-spacing:.05em;\">' + label + '</div>' +\n '<div style=\"font-size:26px;font-weight:700;color:#0f172a;margin:7px 0;letter-spacing:-.02em;\">' + valStr + '</div>' +\n '<div>' + pill + '</div>' +\n '<div style=\"font-size:11px;color:#b0bac9;margin-top:7px;\">from ' + fromStr + '</div>' +\n '</div></td>';\nconst cT = { clicks: num(curT.clicks), impr: num(curT.impressions), ctr: num(curT.ctr), pos: num(curT.position) };\nconst pT = { clicks: num(prevT.clicks), impr: num(prevT.impressions), ctr: num(prevT.ctr), pos: num(prevT.position) };\nconst cards =\n kpiCard('Clicks', fmtInt(cT.clicks), kpiPill(cT.clicks, pT.clicks, true, 'pct'), fmtInt(pT.clicks)) +\n kpiCard('Impressions', fmtInt(cT.impr), kpiPill(cT.impr, pT.impr, true, 'pct'), fmtInt(pT.impr)) +\n kpiCard('Avg CTR', fmtCtr(cT.ctr), kpiPill(cT.ctr, pT.ctr, true, 'pct'), fmtCtr(pT.ctr)) +\n kpiCard('Avg Position', fmtPos(cT.pos), kpiPill(cT.pos, pT.pos, false, 'pos'), fmtPos(pT.pos));\n\nconst th = (label, align) => '<th style=\"padding:10px 12px;text-align:' + align + ';font-size:10px;color:#e2e8f0;text-transform:uppercase;letter-spacing:.05em;font-weight:600;\">' + label + '</th>';\nconst table = (firstCol, rowsHtml) => '<table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"border-collapse:collapse;border:1px solid #eef1f5;border-radius:10px;overflow:hidden;\"><tr style=\"background:#0f172a;\">' + th(firstCol, 'left') + th('Clicks', 'right') + th('Impr', 'right') + th('CTR', 'right') + th('Pos', 'right') + '</tr>' + rowsHtml + '</table>';\n\nconst html =\n'<div style=\"margin:0;padding:0;background:#eef1f5;\">' +\n'<div style=\"max-width:600px;margin:0 auto;font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;background:#ffffff;border-radius:16px;overflow:hidden;\">' +\n '<div style=\"background:#0f172a;padding:30px 32px 26px;\">' +\n '<div style=\"font-size:20px;font-weight:600;color:#ffffff;letter-spacing:-.01em;\">Search Console Weekly Report</div>' +\n '<div style=\"font-size:14px;color:#8ea0b8;margin-top:5px;\">pocketfmmodapk.com</div>' +\n '</div>' +\n '<div style=\"padding:20px 32px 4px;text-align:center;font-size:13px;color:#475569;font-weight:600;\">' + d.currentLabel + ' <span style=\"color:#94a3b8;font-weight:400;\">vs</span> ' + d.previousLabel + '</div>' +\n '<div style=\"padding:12px 24px 22px;\"><table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\"><tr>' + cards + '</tr></table></div>' +\n '<div style=\"padding:0 32px 6px;font-size:13px;font-weight:600;color:#0f172a;\">Top queries</div>' +\n '<div style=\"padding:0 32px 24px;\">' + table('Query', qRows) + '</div>' +\n '<div style=\"padding:0 32px 6px;font-size:13px;font-weight:600;color:#0f172a;\">Top pages</div>' +\n '<div style=\"padding:0 32px 26px;\">' + table('Page', pRows) + '</div>' +\n '<div style=\"background:#fbfcfd;padding:18px 32px;border-top:1px solid #eef1f5;font-size:11px;color:#a8b2c1;line-height:1.6;\">Compares two 7 day windows ending 3 days before send, so the data is final. Green up means better than last week, red down means worse. Lower position is better. Generated ' + d.generatedAt + ' by n8n.</div>' +\n'</div></div>';\n\nconst cp = pT.clicks === 0 ? 0 : Math.round(((cT.clicks - pT.clicks) / pT.clicks) * 1000) / 10;\nconst arrow = cp > 0 ? '\\u25B2' : (cp < 0 ? '\\u25BC' : '');\nconst subject = 'GSC Weekly - pocketfmmodapk.com - ' + fmtInt(cT.clicks) + ' clicks (' + arrow + ' ' + Math.abs(cp).toFixed(1) + '%) - ' + d.currentLabel;\nreturn [{ json: { subject: subject, html: html } }];"
},
"typeVersion": 2
},
{
"id": "2d4867f1-32c4-4d0f-8b98-fc0f8fda18c8",
"name": "Send Email",
"type": "n8n-nodes-base.gmail",
"maxTries": 3,
"position": [
2016,
0
],
"parameters": {
"sendTo": "user@example.com",
"message": "={{ $json.html }}",
"options": {
"appendAttribution": false
},
"subject": "={{ $json.subject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 2.2,
"waitBetweenTries": 5000
},
{
"id": "bb51b7dd-a21b-4c72-89fa-ad9ac0d92db5",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-656,
-144
],
"parameters": {
"width": 480,
"height": 880,
"content": "## Send Weekly Search Console Report\n\n### How it works\n\n1. Trigger fires every Monday at 8 AM to run the weekly SEO report workflow\n2. Date ranges for current and previous week are calculated and stored as variables\n3. Six sequential Google Search Console API calls fetch totals, queries, and pages for both weeks\n4. Custom code aggregates the data and formats it into a readable report\n5. Final report is sent via email to configured recipients\n6. Any API errors during data collection automatically trigger an error alert email\n\n### Setup steps\n\n- - [ ] Configure Google account Service Account credentials with access to Google Search Console API\n- [ ] Set up Gmail credentials for sending both the report and error alert emails\n- [ ] Update the recipient email address in the Send Email node\n- [ ] Verify the Google Search Console property URL is correct in all HTTP Request nodes\n\n### Customization\n\nModify the email recipients or report format in Build Report and Send Email nodes. You can also adjust date range calculations in Build Date Ranges if you need custom reporting periods. "
},
"typeVersion": 1
},
{
"id": "d17551d3-9956-4492-9407-21804dfcaff3",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-144,
192
],
"parameters": {
"color": 7,
"width": 256,
"height": 416,
"content": "## Weekly Schedule Trigger\n\nScheduled trigger that initiates the workflow every Monday at 8 AM to generate weekly SEO performance reports."
},
"typeVersion": 1
},
{
"id": "37e48a17-8ad8-41f7-8b72-4f20c3cc00cc",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
128,
192
],
"parameters": {
"color": 7,
"height": 416,
"content": "## Build Date Ranges\n\nSets current and previous week date ranges for the Google Search Console API queries."
},
"typeVersion": 1
},
{
"id": "401e5f65-4cdc-4c70-9221-aee41447d654",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
384,
-80
],
"parameters": {
"color": 7,
"width": 1344,
"height": 688,
"content": "## Search Console Data Collection\n\nSequential API requests to Google Search Console for search analytics data: totals, queries, and pages for both this week and last week."
},
"typeVersion": 1
},
{
"id": "e1e17152-52df-439b-a513-648e6f0f88e8",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1744,
-192
],
"parameters": {
"color": 7,
"width": 464,
"height": 368,
"content": "## Build and Send Report\n\nCustom code that aggregates all search analytics data and builds a formatted report, then sends it via email."
},
"typeVersion": 1
},
{
"id": "bddb9662-c0c1-4aaf-b046-2f76079701ab",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1744,
192
],
"parameters": {
"color": 7,
"width": 288,
"height": 368,
"content": "## Error Alert Handler\n\nGmail node that receives error signals from all data collection nodes and sends alerts when API requests fail."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": true,
"executionOrder": "v1"
},
"versionId": "776a6556-1e88-49c6-9bf2-1f74935f83b7",
"nodeGroups": [],
"connections": {
"Build Report": {
"main": [
[
{
"node": "Send Email",
"type": "main",
"index": 0
}
]
]
},
"Weekly Mon 8AM": {
"main": [
[
{
"node": "Build Date Ranges",
"type": "main",
"index": 0
}
]
]
},
"Pages Last Week": {
"main": [
[
{
"node": "Build Report",
"type": "main",
"index": 0
}
],
[
{
"node": "Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Pages This Week": {
"main": [
[
{
"node": "Pages Last Week",
"type": "main",
"index": 0
}
],
[
{
"node": "Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Totals Last Week": {
"main": [
[
{
"node": "Queries This Week",
"type": "main",
"index": 0
}
],
[
{
"node": "Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Totals This Week": {
"main": [
[
{
"node": "Totals Last Week",
"type": "main",
"index": 0
}
],
[
{
"node": "Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Build Date Ranges": {
"main": [
[
{
"node": "Totals This Week",
"type": "main",
"index": 0
}
]
]
},
"Queries Last Week": {
"main": [
[
{
"node": "Pages This Week",
"type": "main",
"index": 0
}
],
[
{
"node": "Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Queries This Week": {
"main": [
[
{
"node": "Queries Last Week",
"type": "main",
"index": 0
}
],
[
{
"node": "Error Alert",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googleApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs every Monday at 8 AM, pulls weekly performance data from Google Search Console for a chosen site, builds an HTML report comparing two 7-day periods, and emails the report via Gmail, with a separate alert email sent if any Search Console request fails. Runs on…
Source: https://n8n.io/workflows/17453/ — 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.
Relatórios aos Laboratórios. Uses httpRequest, gmail, formTrigger. Scheduled trigger; 54 nodes.
YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.
14310 Send Overdue Invoice Payment Reminders With Ifirma Gmail Postgrid And Slack. Uses httpRequest, stopAndError, slack, gmail. Scheduled trigger; 53 nodes.
Addendo — Blog Automatico Don Jacinto Nahual. Uses httpRequest, redis, github, gmail. Scheduled trigger; 51 nodes.
Addendo — Blog Automatico Don Jacinto Nahual. Uses httpRequest, redis, github, gmail. Scheduled trigger; 51 nodes.