AutomationFlowsEmail & Gmail › Monitor Website Performance with Pagespeed Insights and Send Alerts

Monitor Website Performance with Pagespeed Insights and Send Alerts

ByDahiana @mssporto on n8n.io

This n8n template automatically monitors website performance using Google's PageSpeed Insights API, compiles detailed reports, and tracks performance trends over time in Google Sheets.

Webhook trigger★★★★☆ complexity20 nodesHTTP RequestGoogle SheetsGmail
Email & Gmail Trigger: Webhook Nodes: 20 Complexity: ★★★★☆ Added:
Monitor Website Performance with Pagespeed Insights and Send Alerts — n8n workflow card showing HTTP Request, Google Sheets, Gmail integration

This workflow corresponds to n8n.io template #8328 — we link there as the canonical source.

This workflow follows the Gmail → 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 →

Download .json
{
  "id": "s9YeIkLvgkThgR3d",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Monitor website performance with PageSpeed Insights and send alerts to Google Sheets",
  "tags": [
    {
      "id": "T3xhK1cIuPex0boX",
      "name": "Templates",
      "createdAt": "2025-09-03T11:06:03.839Z",
      "updatedAt": "2025-09-03T11:06:03.839Z"
    }
  ],
  "nodes": [
    {
      "id": "dfbcd954-aefb-45c0-b0cd-b8f7374e6126",
      "name": "Main Template Explanation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -336,
        -224
      ],
      "parameters": {
        "width": 700,
        "height": 1764,
        "content": "# Monitor website performance with PageSpeed Insights and save to Google Sheets with alerts\n\nThis n8n template automatically monitors website performance using Google's PageSpeed Insights API, compiles detailed reports, and tracks performance trends over time in Google Sheets.\n\n**Use cases:** Agency client monitoring, competitor analysis, performance regression detection, SEO reporting, site migration monitoring, A/B testing performance impact, and maintaining performance SLAs.\n\n## Who's it for\n- Digital agencies monitoring client websites\n- SEO professionals tracking site performance\n- DevOps teams maintaining performance SLAs\n- Business owners wanting automated site monitoring\n\n## How it works\n- **Automated Testing:** Scheduled audits of multiple websites using PageSpeed Insights API\n- **Core Web Vitals:** Tracks LCP, FID, CLS, and overall performance scores\n- **Historical Tracking:** Maintains performance history for trend analysis\n- **Alert System:** Sends notifications when performance drops below thresholds\n- **Detailed Reporting:** Captures specific recommendations and optimization opportunities\n\n## Two Workflow Paths\n1. **Scheduled Audit:** Automatically tests all URLs from Google Sheet on schedule\n2. **On-Demand Testing:** Webhook endpoint for immediate single-URL testing\n\n## How to set up\n1. Get a free PageSpeed Insights API key from Google Cloud Console\n2. Create Google Sheet with columns: URL, Site Name, Category, Alert Threshold, Last_Processed_Date and Device.\n3. Set up Google Sheets API credentials\n4. Configure notification preferences (Slack, email, etc.)\n5. Set audit schedule (daily, weekly, or custom)\n6. Define performance thresholds for alerts\n\n## Requirements\n- Google PageSpeed Insights API key (free)\n- Google Sheets API access\n- n8n instance (cloud or self-hosted)\n- Optional: Slack/email for notifications\n\n## Google Sheet Structure\n**Input Sheet (\"sites\"):**\n- URL, Site_Name, Category, Alert_Threshold, Last_Processed_Date and Device.\n\n**Results Sheet (\"audit_results\"):**\n- Date, URL, Site_Name, Device, Performance_Score, LCP, FID, CLS, Recommendations, Full_Report_URL\n\n## API Usage (On-Demand)\nPOST to webhook:\n```json\n{\n  \"url\": \"https://example.com\",\n  \"site_name\": \"Example Site\",\n  \"alert_threshold\": 75\n}\n```\n\n## How to customize\n- Add custom performance thresholds per site\n- Include additional metrics (accessibility, SEO, best practices)\n- Connect to other dashboards (Data Studio, Grafana)\n- Add competitor benchmarking\n- Integrate with project management tools for issue tracking\n- Set up different notification channels based on severity"
      },
      "typeVersion": 1
    },
    {
      "id": "d1cedc16-b144-4a4f-8506-be91607bd7db",
      "name": "On-Demand Testing Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        960
      ],
      "parameters": {
        "color": 4,
        "width": 600,
        "height": 112,
        "content": "## On-Demand Testing\n\nWebhook endpoint for immediate single-URL performance testing"
      },
      "typeVersion": 1
    },
    {
      "id": "2ffb1551-9549-49a9-aeee-fdb5c12a87bf",
      "name": "Format Webhook Input",
      "type": "n8n-nodes-base.set",
      "position": [
        672,
        1136
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "name": "URL",
              "type": "string",
              "value": "={{ $json.body.url }}"
            },
            {
              "name": "Site_Name",
              "type": "string",
              "value": "={{ $json.body.site_name || 'On-Demand Test' }}"
            },
            {
              "name": "Alert_Threshold",
              "type": "number",
              "value": "={{ $json.body.alert_threshold || 75 }}"
            },
            {
              "name": "device",
              "type": "string",
              "value": "={{ $json.body.device || 'mobile' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8ae6a002-9201-4adb-8cca-369097c6bbeb",
      "name": "Run On-Demand Test",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        880,
        1136
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/pagespeedonline/v5/runPagespeed",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $json.URL }}"
            },
            {
              "name": "key",
              "value": "YOUR-API-KEY"
            },
            {
              "name": "strategy",
              "value": "={{ $json.device }}"
            },
            {
              "name": "category",
              "value": "performance"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "7994e14d-6cfc-4db8-9fcb-da673ac03a98",
      "name": "Process On-Demand Results",
      "type": "n8n-nodes-base.code",
      "position": [
        1072,
        1136
      ],
      "parameters": {
        "jsCode": "// Same processing logic as scheduled audit\nconst response = $input.first().json;\nconst webhookData = $('Format Webhook Input').item.json;\n\n// Extract key metrics\nconst lighthouseResult = response.lighthouseResult;\nconst categories = lighthouseResult.categories;\nconst audits = lighthouseResult.audits;\n\n// Core Web Vitals\nconst lcp = audits['largest-contentful-paint']?.displayValue || 'N/A';\nconst fid = audits['max-potential-fid']?.displayValue || 'N/A';\nconst cls = audits['cumulative-layout-shift']?.displayValue || 'N/A';\n\n// Performance score (0-100)\nconst performanceScore = Math.round(categories.performance.score * 100);\n\n// Key recommendations\nconst recommendations = [];\nif (audits['unused-css-rules'] && audits['unused-css-rules'].score < 0.5) {\n  recommendations.push('Remove unused CSS');\n}\nif (audits['render-blocking-resources'] && audits['render-blocking-resources'].score < 0.5) {\n  recommendations.push('Eliminate render-blocking resources');\n}\nif (audits['unminified-css'] && audits['unminified-css'].score < 0.5) {\n  recommendations.push('Minify CSS');\n}\nif (audits['unminified-javascript'] && audits['unminified-javascript'].score < 0.5) {\n  recommendations.push('Minify JavaScript');\n}\nif (audits['uses-optimized-images'] && audits['uses-optimized-images'].score < 0.5) {\n  recommendations.push('Optimize images');\n}\n\nreturn {\n  json: {\n    success: true,\n    audit_date: new Date().toISOString(),\n    url: webhookData.URL,\n    site_name: webhookData.Site_Name,\n    device: webhookData.device,\n    performance_score: performanceScore,\n    core_web_vitals: {\n      lcp: lcp,\n      fid: fid,\n      cls: cls\n    },\n    recommendations: recommendations,\n    full_report_url: response.id ? `https://pagespeed.web.dev/report?url=${encodeURIComponent(webhookData.URL)}` : 'N/A',\n    raw_scores: {\n      performance: categories.performance.score,\n      accessibility: categories.accessibility?.score || null,\n      'best-practices': categories['best-practices']?.score || null,\n      seo: categories.seo?.score || null\n    }\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "58e18dcc-9fce-4648-a3b9-51754f2e6c2b",
      "name": "Return Audit Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1280,
        1136
      ],
      "parameters": {
        "options": {},
        "respondWith": "allIncomingItems"
      },
      "typeVersion": 1.4
    },
    {
      "id": "ae4b5083-903d-450b-8cc0-b9f49aaf714a",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "onError": "continueRegularOutput",
      "maxTries": 2,
      "position": [
        464,
        1136
      ],
      "parameters": {
        "path": "PATH_ID",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "executeOnce": false,
      "retryOnFail": true,
      "typeVersion": 2.1
    },
    {
      "id": "e8b625d3-44fa-4599-accf-ea576a05708b",
      "name": "Scheduled Audit Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        -208
      ],
      "parameters": {
        "color": 3,
        "width": 600,
        "height": 144,
        "content": "## Scheduled Audit Workflow\n\nAutomatically tests all websites from Google Sheet on a defined schedule. \n\nSelect your prefereed interval."
      },
      "typeVersion": 1
    },
    {
      "id": "505706c1-0d0f-48c6-8585-b44cb98d114d",
      "name": "Run PageSpeed Test",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1360,
        64
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/pagespeedonline/v5/runPagespeed",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $json.URL }}"
            },
            {
              "name": "key",
              "value": "=YOUR-API-KEY"
            },
            {
              "name": "strategy",
              "value": "={{ $json.Device }}"
            },
            {
              "name": "category",
              "value": "={{ $('Load Sites from Google Sheet').item.json.Category }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "711ea54b-01aa-424d-904c-be5d30a6c1b9",
      "name": "Process Audit Results",
      "type": "n8n-nodes-base.code",
      "position": [
        1648,
        64
      ],
      "parameters": {
        "jsCode": "const response = $input.first().json;\nconst siteData = $('Load Sites from Google Sheet').item.json;\n\n// Extract key metrics\nconst lighthouseResult = response.lighthouseResult;\nconst categories = lighthouseResult.categories;\nconst audits = lighthouseResult.audits;\n\n// Core Web Vitals\nconst lcp = audits['largest-contentful-paint']?.displayValue || 'N/A';\nconst fid = audits['max-potential-fid']?.displayValue || 'N/A';\nconst cls = audits['cumulative-layout-shift']?.displayValue || 'N/A';\n\n// Performance score (0-100)\nconst performanceScore = Math.round(categories.performance.score * 100);\n\n// IMPROVED ALERT LOGIC\nconst alertThreshold = parseInt(siteData.Alert_Threshold) || 75; // Ensure it's a number\nconst shouldAlert = performanceScore < alertThreshold;\n\n// SEVERITY LEVELS for better alerting\nlet alertSeverity = 'info';\nlet alertMessage = 'Performance within acceptable range';\n\nif (performanceScore < 30) {\n    alertSeverity = 'critical';\n    alertMessage = '\ud83d\udea8 CRITICAL: Extremely poor performance';\n} else if (performanceScore < 50) {\n    alertSeverity = 'high';\n    alertMessage = '\u26a0\ufe0f HIGH: Poor performance affecting user experience';\n} else if (performanceScore < alertThreshold) {\n    alertSeverity = 'medium';\n    alertMessage = '\u26a0\ufe0f MEDIUM: Performance below threshold';\n} else if (performanceScore < 80) {\n    alertSeverity = 'low';\n    alertMessage = '\u2139\ufe0f LOW: Room for improvement';\n}\n\n// Key recommendations (unchanged)\nconst recommendations = [];\nif (audits['unused-css-rules'] && audits['unused-css-rules'].score < 0.5) {\n    recommendations.push('Remove unused CSS');\n}\nif (audits['render-blocking-resources'] && audits['render-blocking-resources'].score < 0.5) {\n    recommendations.push('Eliminate render-blocking resources');\n}\n// ... other recommendations\n\nreturn {\n    json: {\n        date: new Date().toISOString().split('T')[0],\n        url: siteData.URL,\n        site_name: siteData.Site_Name,\n        category: siteData.Category || 'General',\n        device: $json.device,\n        performance_score: performanceScore,\n        lcp: lcp,\n        fid: fid,\n        cls: cls,\n        recommendations: recommendations.join(', ') || 'No major issues detected',\n        full_report_url: response.id ? `https://pagespeed.web.dev/report?url=${encodeURIComponent(siteData.URL)}` : 'N/A',\n        \n        // IMPROVED ALERT DATA\n        should_alert: shouldAlert,\n        alert_threshold: alertThreshold,\n        alert_severity: alertSeverity,\n        alert_message: alertMessage,\n        \n        // PERFORMANCE CATEGORY\n        performance_category: performanceScore >= 90 ? 'excellent' : \n                             performanceScore >= 50 ? 'needs_improvement' : 'poor'\n    }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "882e6e4f-a9a6-4dd8-abd3-ab4262781b7d",
      "name": "Save Audit Results",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1904,
        64
      ],
      "parameters": {
        "columns": {
          "value": {
            "CLS": "={{ $json.cls }}",
            "FID": "={{ $json.fid }}",
            "LCP": "={{ $json.lcp }}",
            "URL": "={{ $json.url }}",
            "Date": "={{ $json.date }}",
            "Device": "{{ $json.Device }}",
            "Site_Name": "={{ $json.site_name }}",
            "Recommendatios": "={{ $json.recommendations }}",
            "Full_Report_URL": "={{ $json.full_report_url }}",
            "Performance_Score": "={{ $json.performance_score }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Site_Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Site_Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Device",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Device",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Performance_Score",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Performance_Score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LCP",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LCP",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "FID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "FID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CLS",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "CLS",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Recommendatios",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Recommendatios",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Full_Report_URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Full_Report_URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1367646124,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/158cVb-BnFu3eGiabTrMR59f-Yl5ThsUMWC2WPERzaAI/edit#gid=1367646124",
          "cachedResultName": "audit_results"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "158cVb-BnFu3eGiabTrMR59f-Yl5ThsUMWC2WPERzaAI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/158cVb-BnFu3eGiabTrMR59f-Yl5ThsUMWC2WPERzaAI/edit?usp=drivesdk",
          "cachedResultName": "n8n_website_audite_templace"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "24a4a27d-d746-4d8b-a4a3-df33086f29db",
      "name": "Check Alert Threshold",
      "type": "n8n-nodes-base.if",
      "position": [
        2352,
        64
      ],
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $('Process Audit Results').item.json.should_alert }}",
              "value2": true
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2ddf6c22-2094-47d6-a1ce-32e01693e43b",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        464,
        64
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "28198a35-077b-46bb-8f26-b0a4fc432d52",
      "name": "Filter Unprocessed Sites",
      "type": "n8n-nodes-base.code",
      "position": [
        1024,
        64
      ],
      "parameters": {
        "jsCode": "// Get today's date in YYYY-MM-DD format\nconst today = new Date().toISOString().split('T')[0];\n\nconst sitesToProcess = [];\n\nfor (const site of $input.all()) {\n  const lastProcessed = site.json.Last_Processed_Date;\n  \n  // If never processed OR processed on a different date, include it\n  if (!lastProcessed || lastProcessed === '' || lastProcessed !== today) {\n    sitesToProcess.push(site);\n  }\n}\n\nreturn sitesToProcess;"
      },
      "typeVersion": 2
    },
    {
      "id": "7988d3d0-5f19-49d4-a189-4d43d419a8d0",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2656,
        -32
      ],
      "parameters": {
        "sendTo": "EMAIL-THE-PERSON-IN-CHARGE",
        "message": "={{ $('Process Audit Results').item.json.alert_message }}",
        "options": {},
        "subject": "=Audit results from {{ $('Process Audit Results').item.json.date }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "5ffb3bca-94ea-427f-b0d6-07b77beacfb7",
      "name": "Scheduled Audit Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2848,
        -48
      ],
      "parameters": {
        "color": 7,
        "width": 328,
        "height": 128,
        "content": "## Choose what works for you\n\nSend an email or a Slack notification."
      },
      "typeVersion": 1
    },
    {
      "id": "d8c76ba1-07bc-4905-a968-bea291565885",
      "name": "Scheduled Audit Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        896,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 392,
        "height": 432,
        "content": "### Filter Unprocessed Sites\n\n**Purpose**: Prevents duplicate processing on the same day while allowing re-processing on future days.\nHow it works:\n\nCompares today's date (YYYY-MM-DD format) with each site's `Last_Processed_Date`\nSkips sites already processed today\nProcesses sites with empty dates or different dates\nPerfect for scheduled audits (daily/weekly/monthly)\n\n**Example:**\n\nToday: Processes all 4 sites\nLater today: Skips all 4 sites (already done)\nTomorrow: Processes all 4 sites again (new day)\n\n**Date format**: Uses `2025-09-05` format to match Google Sheets"
      },
      "typeVersion": 1
    },
    {
      "id": "7215e78a-e6b7-4725-9f99-1152aac6d1e6",
      "name": "Load Sites from Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "maxTries": 2,
      "position": [
        704,
        64
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1748870974,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/158cVb-BnFu3eGiabTrMR59f-Yl5ThsUMWC2WPERzaAI/edit#gid=1748870974",
          "cachedResultName": "sites"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "158cVb-BnFu3eGiabTrMR59f-Yl5ThsUMWC2WPERzaAI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/158cVb-BnFu3eGiabTrMR59f-Yl5ThsUMWC2WPERzaAI/edit?usp=drivesdk",
          "cachedResultName": "n8n_website_audite_templace"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    },
    {
      "id": "9fcc0d28-480e-4674-a2d1-74a795afd90a",
      "name": "Skip Alert (Performance OK)",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2656,
        160
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "8e4cac66-8c85-418e-9a42-54fd3352496f",
      "name": "Update Audit Date",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2144,
        64
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.URL }}",
              "lookupColumn": "URL"
            },
            {
              "lookupValue": "={{ new Date().toISOString().split('T')[0] }}",
              "lookupColumn": "Last_Processed_Date"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1748870974,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/158cVb-BnFu3eGiabTrMR59f-Yl5ThsUMWC2WPERzaAI/edit#gid=1748870974",
          "cachedResultName": "sites"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "158cVb-BnFu3eGiabTrMR59f-Yl5ThsUMWC2WPERzaAI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/158cVb-BnFu3eGiabTrMR59f-Yl5ThsUMWC2WPERzaAI/edit?usp=drivesdk",
          "cachedResultName": "n8n_website_audite_templace"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "e0e8a69b-255e-4291-9df9-8503a62913aa",
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Format Webhook Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Load Sites from Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Audit Date": {
      "main": [
        [
          {
            "node": "Check Alert Threshold",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run On-Demand Test": {
      "main": [
        [
          {
            "node": "Process On-Demand Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run PageSpeed Test": {
      "main": [
        [
          {
            "node": "Process Audit Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Audit Results": {
      "main": [
        [
          {
            "node": "Update Audit Date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Webhook Input": {
      "main": [
        [
          {
            "node": "Run On-Demand Test",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Alert Threshold": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skip Alert (Performance OK)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Audit Results": {
      "main": [
        [
          {
            "node": "Save Audit Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Unprocessed Sites": {
      "main": [
        [
          {
            "node": "Run PageSpeed Test",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process On-Demand Results": {
      "main": [
        [
          {
            "node": "Return Audit Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Sites from Google Sheet": {
      "main": [
        [
          {
            "node": "Filter Unprocessed Sites",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This n8n template automatically monitors website performance using Google's PageSpeed Insights API, compiles detailed reports, and tracks performance trends over time in Google Sheets.

Source: https://n8n.io/workflows/8328/ — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

Automate WhatsApp communication for recruitment agencies with an interactive, structured customer experience. This workflow handles pricing inquiries, request submissions, tracking, complaints, and hu

HTTP Request, Google Sheets, Gmail +1
Email & Gmail

Ticketing Backend automates registration, QR-ticket generation, email delivery, and check-in validation using Google Sheets, Gmail, and a webhook scanner — reducing manual ticket prep from ~3 hours to

Google Sheets, HTTP Request, Gmail
Email & Gmail

Who is this for? This template is ideal for event organizers, conference managers, and community teams who need an automated participant management system. Perfect for workshops, conferences, meetups,

Google Sheets, HTTP Request, Gmail +1
Email & Gmail

Streamline and standardize your entire client onboarding process with a single end-to-end automation. 🚀📋 This workflow captures detailed client intake data via webhook, automatically creates a fully s

Slack, Asana, HTTP Request +4
Email & Gmail

Human Approval AI Response. Uses httpRequest, slack, gmail, googleSheets. Webhook trigger; 20 nodes.

HTTP Request, Slack, Gmail +2