Build an SEO Audit Dashboard in Google Sheets with the SEOPeek API (2026)
Every agency and freelancer has the same problem: clients want SEO reports, but enterprise tools like Ahrefs ($99/mo) and Semrush ($130/mo) destroy margins on small accounts. What if you could build a live SEO audit dashboard in Google Sheets—the tool your clients already know—powered by a free API that runs 20 on-page checks in under 2 seconds? This guide walks through the entire setup, from first API call to automated weekly reports, using SEOPeek and Google Apps Script.
Why Agencies and Freelancers Need Automated SEO Monitoring in Spreadsheets
Most SEO professionals live in spreadsheets. Client URL lists, keyword tracking sheets, content calendars, reporting decks—Google Sheets is the connective tissue of agency work. Yet when it comes to actual SEO data, teams are forced to export CSVs from expensive dashboards, manually copy-paste audit results, or build complex integrations with tools that cost more than the client retainer.
The result is one of two bad outcomes. Either the agency pays $99-200/mo per tool and eats the cost on smaller clients, or they skip automated monitoring entirely and deliver stale reports based on one-time audits. Neither approach scales.
An seo audit api google sheets dashboard solves this by pulling live audit data directly into the spreadsheet your team already uses. No context-switching, no CSV exports, no expensive subscriptions. The SEOPeek API gives you 50 free audits per day—enough to monitor 50 client pages daily without spending a dollar. For larger portfolios, $9/mo covers 1,000 audits. Compare that to the cost of a single Ahrefs seat.
The approach also gives you total control over presentation. Unlike locked-down SaaS dashboards, a Google Sheet lets you add your own branding, create custom scoring views, build charts that match your reporting style, and share individual tabs with clients who never need to see the raw data.
What the SEOPeek API Returns
Before writing any code, it helps to understand exactly what data you will be working with. The SEOPeek API accepts a single URL and returns a JSON response containing:
- score — A numeric value from 0 to 100 representing overall on-page SEO health
- grade — A letter grade from A (90-100) through F (below 40)
- checks — An object with 20 individual on-page checks, each containing a
passboolean, extractedvalue, and human-readablemessage
The 20 checks cover title tag, meta description, H1-H6 heading hierarchy, Open Graph tags (og:title, og:description, og:image), Twitter Card tags, canonical URL, structured data (JSON-LD), image alt text coverage, mobile viewport, language attribute, character encoding, favicon, HTTPS status, internal and external link counts, and word count.
Here is what a raw API response looks like:
curl "https://seopeek.web.app/api/audit?url=https://example.com"
{
"url": "https://example.com",
"score": 74,
"grade": "C",
"checks": {
"title": { "pass": true, "value": "Example Domain", "message": "Title tag found (14 chars)" },
"metaDescription": { "pass": false, "value": "", "message": "Missing meta description" },
"h1": { "pass": true, "value": "Example Domain", "message": "One H1 tag found" },
"ogTags": { "pass": false, "value": "", "message": "Missing og:title, og:description" },
"structuredData": { "pass": false, "value": "", "message": "No JSON-LD found" },
"https": { "pass": true, "value": "https", "message": "Page served over HTTPS" }
// ... 14 more checks
}
}
The flat, consistent schema is what makes this API ideal for spreadsheet integration. Every check follows the same structure. No nested arrays, no variable field names, no defensive parsing logic required in Apps Script.
Step 1: Set Up Your Google Sheet
Create a new Google Sheet with the following structure. You will need two sheets (tabs):
Sheet 1: "Audit Results"
This is your main dashboard. Set up columns as follows:
- Column A: URL
- Column B: Score (0-100)
- Column C: Grade (A-F)
- Column D: Title
- Column E: Meta Description
- Column F: H1
- Column G: OG Tags
- Column H: Structured Data
- Column I: HTTPS
- Column J: Image Alt Text
- Column K: Last Audited
Add your client URLs in Column A starting from row 2. Row 1 is your header row. You can add as many URLs as your plan allows—50 per day on free, 1,000 per month on Starter.
Sheet 2: "Score History"
This sheet tracks scores over time for trend analysis. Columns:
- Column A: Date
- Column B onwards: One column per URL, containing that day's score
This second sheet is what powers your sparkline charts and trend visualizations later.
Step 2: Write the Apps Script Function
Open your Google Sheet, go to Extensions > Apps Script, and replace the default code with the following. This is the complete, production-ready script:
/**
* Calls the SEOPeek API and returns audit data for a URL.
* Free tier: 50 audits/day, no API key needed.
*/
function auditUrl(url) {
var endpoint = "https://seopeek.web.app/api/audit?url=" + encodeURIComponent(url);
var options = {
"method": "get",
"muteHttpExceptions": true
};
var response = UrlFetchApp.fetch(endpoint, options);
var json = JSON.parse(response.getContentText());
return json;
}
/**
* Runs audits for all URLs in the "Audit Results" sheet.
* Populates score, grade, and individual check results.
*/
function runAllAudits() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Audit Results");
var historySheet = ss.getSheetByName("Score History");
var lastRow = sheet.getLastRow();
if (lastRow < 2) return; // No URLs to audit
var urls = sheet.getRange("A2:A" + lastRow).getValues();
var today = new Date().toISOString().split("T")[0];
var scores = [];
for (var i = 0; i < urls.length; i++) {
var url = urls[i][0];
if (!url || url === "") continue;
try {
var result = auditUrl(url);
var row = i + 2;
// Populate main columns
sheet.getRange(row, 2).setValue(result.score); // Score
sheet.getRange(row, 3).setValue(result.grade); // Grade
sheet.getRange(row, 4).setValue(result.checks.title.pass ? "Pass" : "Fail");
sheet.getRange(row, 5).setValue(result.checks.metaDescription.pass ? "Pass" : "Fail");
sheet.getRange(row, 6).setValue(result.checks.h1.pass ? "Pass" : "Fail");
sheet.getRange(row, 7).setValue(result.checks.ogTags.pass ? "Pass" : "Fail");
sheet.getRange(row, 8).setValue(result.checks.structuredData.pass ? "Pass" : "Fail");
sheet.getRange(row, 9).setValue(result.checks.https.pass ? "Pass" : "Fail");
sheet.getRange(row, 10).setValue(result.checks.imgAlt.pass ? "Pass" : "Fail");
sheet.getRange(row, 11).setValue(today); // Last Audited
scores.push(result.score);
// Rate limiting: pause 1.5s between calls to stay well within limits
Utilities.sleep(1500);
} catch (e) {
Logger.log("Error auditing " + url + ": " + e.message);
scores.push("");
}
}
// Append today's scores to the history sheet
if (historySheet && scores.length > 0) {
var historyRow = [today].concat(scores);
historySheet.appendRow(historyRow);
}
}
/**
* Audits a single URL from a cell. Use as a custom function:
* =SEOPEEK_SCORE("https://example.com")
*/
function SEOPEEK_SCORE(url) {
if (!url) return "Enter a URL";
try {
var result = auditUrl(url);
return result.score;
} catch (e) {
return "Error: " + e.message;
}
}
/**
* Returns the grade for a single URL.
* =SEOPEEK_GRADE("https://example.com")
*/
function SEOPEEK_GRADE(url) {
if (!url) return "Enter a URL";
try {
var result = auditUrl(url);
return result.grade;
} catch (e) {
return "Error: " + e.message;
}
}
Save the script with Ctrl+S (or Cmd+S on Mac). The first time you run runAllAudits(), Google will prompt you to authorize the script to make external HTTP requests. Accept the permissions—the only external call is to the SEOPeek API.
No API key required. The SEOPeek free tier does not need authentication. Just call the endpoint. If you upgrade to a paid plan and receive an API key, add it as a query parameter: ?url=...&key=YOUR_KEY
Step 3: Build the Dashboard with Conditional Formatting
Raw data in a spreadsheet is useful. A color-coded dashboard is actionable. Here is how to make your audit results visually scannable in seconds.
Score Column (B) — Color Scale
Select column B (all score cells), go to Format > Conditional formatting, and add a color scale:
- Min (0): Red (#EF4444)
- Midpoint (60): Yellow (#F59E0B)
- Max (100): Green (#10B981)
This gives you an instant heat map. Pages scoring below 60 glow red. Pages above 80 are green. Everything in between shows the gradient, making it easy to spot which client pages need immediate attention.
Grade Column (C) — Text Rules
Add conditional formatting rules for text matching:
- "A" — Bold, green text (#10B981)
- "B" — Bold, teal text (#14B8A6)
- "C" — Bold, yellow text (#F59E0B)
- "D" — Bold, orange text (#F97316)
- "F" — Bold, red text (#EF4444)
Pass/Fail Columns (D-J) — Binary Highlighting
For each check column, add two rules:
- "Pass" — Green background, white text
- "Fail" — Red background, white text
The result is a dashboard where you can scan 50 client URLs at a glance and instantly see which pages have issues with meta descriptions, OG tags, structured data, or any other check.
Sparklines for Score Trends
In the "Audit Results" sheet, add a column L called "Trend". In cell L2, enter this formula (assuming the first URL's scores are in column B of the Score History sheet):
=SPARKLINE('Score History'!B:B, {"charttype","line";"color","#10B981";"linewidth",2})
Copy this down for each URL, adjusting the column reference. Each cell now shows a miniature line chart of that URL's score over time. Clients love seeing the upward trend after you fix their SEO issues.
Step 4: Automate with Time-Based Triggers
Running audits manually defeats the purpose of a monitoring dashboard. Google Apps Script lets you set up triggers that run your runAllAudits() function automatically.
In the Apps Script editor, go to the clock icon on the left sidebar (Triggers), then click + Add Trigger:
- Function: runAllAudits
- Event source: Time-driven
- Type: Day timer (for daily) or Week timer (for weekly)
- Time of day: Pick an off-peak hour like 6-7 AM
Once saved, your dashboard updates itself. Every morning when you open the sheet, fresh audit data is already there. The Score History sheet accumulates a new row each run, building the trend data that powers your sparklines.
Trigger execution limits: Google Apps Script has a 6-minute execution limit per run. With the 1.5-second delay between API calls, you can audit roughly 200 URLs per trigger execution. For larger portfolios, split URLs across multiple sheets or stagger triggers.
Step 5: Bulk Audit Multiple URLs and Track Changes
The basic setup covers a single list of URLs. Real agency workflows require more structure. Here are two patterns for scaling up.
Pattern 1: One Tab Per Client
Create a separate sheet tab for each client. Name them "Client: Acme Corp", "Client: Widget Inc", etc. Update the runAllAudits() function to loop through all sheets whose names start with "Client:":
function runAllClientAudits() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
for (var s = 0; s < sheets.length; s++) {
var sheetName = sheets[s].getName();
if (sheetName.indexOf("Client:") !== 0) continue;
var sheet = sheets[s];
var lastRow = sheet.getLastRow();
if (lastRow < 2) continue;
var urls = sheet.getRange("A2:A" + lastRow).getValues();
for (var i = 0; i < urls.length; i++) {
var url = urls[i][0];
if (!url) continue;
try {
var result = auditUrl(url);
var row = i + 2;
sheet.getRange(row, 2).setValue(result.score);
sheet.getRange(row, 3).setValue(result.grade);
sheet.getRange(row, 11).setValue(new Date().toISOString().split("T")[0]);
Utilities.sleep(1500);
} catch (e) {
Logger.log("Error: " + e.message);
}
}
}
}
Pattern 2: Score Change Alerts
Add an email notification when a page's score drops by more than 10 points. Insert this into your audit loop after setting the score:
// After setting the new score, check for drops
var previousScore = sheet.getRange(row, 2).getValue();
sheet.getRange(row, 2).setValue(result.score);
if (previousScore && (previousScore - result.score) > 10) {
MailApp.sendEmail(
"you@agency.com",
"SEO Score Drop Alert: " + url,
url + " dropped from " + previousScore + " to " + result.score +
" (grade: " + result.grade + "). Check it now."
);
}
This gives you proactive monitoring. If a client's developer accidentally removes meta tags during a deploy, you know about it the next morning—before the client notices search traffic dropping.
Use Case: Agency White-Label Reporting
The Google Sheets approach is uniquely powerful for agencies because of sharing controls. You can:
- Share a read-only tab with each client showing only their URLs, scores, grades, and trend charts. They see a professional dashboard without knowing it runs on a free API.
- Brand the sheet with your agency logo, colors, and header. Google Sheets supports images in cells and custom header formatting. The SEOPeek API is invisible to the end client.
- Export to PDF with one click for clients who prefer email attachments. The conditional formatting and sparklines render correctly in PDF exports.
- Duplicate the template for each new client in seconds. The Apps Script code stays attached, so each client sheet is a self-contained audit dashboard.
For freelancers, this workflow replaces tools like Ahrefs for on-page reporting at a fraction of the cost. You can even use StackPeek in the same sheet to detect client tech stacks, or OGPeek to verify social preview images are rendering correctly across all client pages.
Pricing: SEOPeek vs the Enterprise Tools
Let us compare what it costs to get on-page SEO audit data into a spreadsheet dashboard:
- SEOPeek Free: $0/mo — 50 audits per day, no signup, no API key. Enough for freelancers monitoring up to 50 client pages daily.
- SEOPeek Starter: $9/mo — 1,000 audits per month. Enough for small agencies with 5-10 clients.
- SEOPeek Business: $29/mo — 10,000 audits per month. Enough for mid-size agencies with 50+ clients.
- Ahrefs Lite: $99/mo — Includes site audit but also backlinks, keywords, and rank tracking you may not need for spreadsheet reporting.
- Semrush Pro: $130/mo — Similar bundled approach with features beyond on-page audits.
If your workflow is "audit client pages and show results in Google Sheets," you are paying $90-120/mo more than necessary with Ahrefs or Semrush. SEOPeek gives you the on-page audit data you actually need, in the JSON format that Apps Script can parse directly, at a price that makes sense even for your smallest client.
Annual savings for a 10-client agency: Switching from Ahrefs Lite ($99/mo) to SEOPeek Starter ($9/mo) saves $1,080 per year. That is money that goes directly back into your margin.
Advanced: Custom Functions for One-Off Lookups
The script above includes two custom functions you can use directly in cell formulas:
=SEOPEEK_SCORE("https://example.com") // Returns: 74
=SEOPEEK_GRADE("https://example.com") // Returns: "C"
These are useful when a client sends you a one-off URL to check, or when you want to audit a competitor page without adding it to the main dashboard. Type the formula in any cell, and the score or grade appears in seconds.
Note that custom functions in Google Sheets have a 30-second execution timeout. The SEOPeek API responds in under 2 seconds, so this is never an issue in practice. However, custom functions do count toward your daily audit limit, so use the batch runAllAudits() function for regular monitoring and save custom functions for ad-hoc checks.
Frequently Asked Questions
Can I use the SEOPeek API in Google Sheets for free?
Yes. SEOPeek offers 50 free audits per day with no signup and no API key required. For most freelancers and small agencies tracking 10-30 client pages, the free tier is more than enough. If you need more volume, the Starter plan is $9/mo for 1,000 audits.
How often can I automatically run SEO audits from Google Sheets?
Google Apps Script supports time-based triggers that can run every minute, every hour, daily, or weekly. For most SEO monitoring use cases, a daily or weekly trigger is ideal. Each trigger run can audit as many URLs as your SEOPeek plan allows, subject to the 6-minute Apps Script execution limit.
What data does the SEOPeek API return for each audit?
The API returns a JSON response containing a numeric score (0-100), a letter grade (A through F), and 20 individual on-page checks. Each check covers a specific factor: title tag, meta description, heading hierarchy, OG tags, Twitter Cards, structured data, image alt text, HTTPS status, canonical URL, viewport, language, encoding, favicon, links, and word count. Every check includes a pass boolean, the extracted value, and a human-readable message.
Can I audit multiple URLs in bulk from Google Sheets?
Yes. The runAllAudits() function loops through every URL in your spreadsheet column and populates results row by row. You can audit 50 URLs per day on the free tier, 1,000 per month on Starter ($9/mo), or up to 10,000 per month on Business ($29/mo). For very large lists, split URLs across multiple trigger executions to stay within the Apps Script timeout.
How does this compare to paying for Ahrefs or Semrush for SEO reporting?
Ahrefs starts at $99/mo and Semrush at $130/mo. Both include backlink analysis, keyword research, and rank tracking that SEOPeek does not offer. But if your reporting only requires on-page audit data—scores, grades, meta tag checks, structured data validation—then SEOPeek at $9/mo (or free) saves you $90-120/mo. The Google Sheets integration also gives you full control over report formatting, branding, and client sharing.
Conclusion
Building an SEO audit dashboard in Google Sheets with the SEOPeek API takes about 15 minutes. You get a live, auto-updating dashboard with scores, grades, pass/fail checks, trend sparklines, and email alerts—all inside the tool your team and clients already use daily. No expensive subscriptions, no CSV exports, no context-switching between platforms.
The free tier covers 50 audits per day. The $9/mo Starter plan handles most agency workloads. And because it is Google Sheets, you can duplicate, share, brand, and export reports with zero additional tooling. Start with the script above, add your client URLs, and run your first batch audit today.
Start Auditing for Free — No Signup Required
50 audits per day, 20 on-page checks, sub-2-second responses. Copy the Apps Script code above into your Google Sheet and run your first audit in under a minute.
Run a free audit →