How to audit a website's SEO and JSON-LD with a single API call
Checking a page's SEO usually means opening five different tools: one for the title and meta description, another for Open Graph tags, another for canonicals and indexability, another for the sitemap, and yet another to
Checking a page's SEO usually means opening five different tools: one for the title and meta description, another for Open Graph tags, another for canonicals and indexability, another for the sitemap, and yet another to validate JSON-LD.
I got tired of that, so I built PageSignal: an API that audits any public URL in a single request and returns an explainable report, so you know not just what failed but why.
What it checks
- Title and meta description: length, and duplicate tags on the same page
- Open Graph and Twitter Card tags: and which recommended ones are missing
-
Indexability: meta robots, googlebot and the
X-Robots-Tagheader combined into one verdict - Canonical URL: missing, empty, duplicated, self-referencing or pointing elsewhere
- robots.txt and XML sitemap discovery
- JSON-LD: every block parsed and validated, with its schema types
- Headings, image ALT coverage, internal and external links
- A 0–100 score where every rule shows its points, severity and the reason
Try it without signing up
There's a live demo where you paste a URL and get the score and the top issues to fix:
👉 https://pagesignal.alorenzom.com/demo
Or straight from your terminal, no key needed (3 checks per day):
curl -s https://pagesignal.alorenzom.com/demo/api/audit \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com/"}'
The demo returns a summary. The full API returns the complete report — here's a real, unedited one for python.org.
Call the full API
With a free RapidAPI key:
curl --get 'https://pagesignal-seo-audit-metadata-json-ld-validator.p.rapidapi.com/v1/audit' \
--data-urlencode 'url=https://www.python.org/' \
-H 'X-RapidAPI-Host: pagesignal-seo-audit-metadata-json-ld-validator.p.rapidapi.com' \
-H "X-RapidAPI-Key: $RAPIDAPI_KEY"
Example output
This is a trimmed, real response for https://www.python.org/:
{
"success": true,
"network": {
"final_url": "https://www.python.org/",
"status_code": 200,
"response_time_ms": 113,
"redirect_count": 0
},
"quality_score": {
"score": 68,
"grade": "C",
"errors_count": 1,
"warnings_count": 4,
"breakdown": [
{
"rule_id": "title_check",
"severity": "warning",
"max_points": 15,
"points_impact": -6,
"message": "Your title is shorter than recommended (30–60 characters). Consider adding primary keywords or brand context."
},
{
"rule_id": "xml_sitemap_check",
"severity": "error",
"max_points": 10,
"points_impact": -10,
"message": "No XML sitemap was detected at common locations."
}
]
},
"diagnostics": { "http_ok": true, "likely_client_rendered": false, "notes": [] },
"title": { "status": "warning", "value": "Welcome to Python.org", "length": 21 },
"indexability": { "status": "healthy", "is_indexable": true, "raw_directives": "index, follow" },
"canonical": { "status": "warning", "is_present": false, "badge": "Missing" },
"structured_data": {
"status": "healthy",
"blocks_detected": 1,
"valid_blocks": 1,
"invalid_blocks": 0,
"blocks": [{ "schema_types": ["WebSite"], "errors": [] }]
}
}
Every point lost comes with a message, so you can show your users exactly what to fix instead of a bare number.
Fail your CI build when SEO breaks
Here's a small script that audits a list of URLs and exits with code 1 if any page breaks a rule you care about. Save it as seo-check.mjs (Node 18+, no dependencies):
js
// seo-check.mjs: audits a list of URLs and exits with code 1 if any of them
// breaks a rule you care about, so it can stop a CI pipeline.
const HOST = 'pagesignal-seo-audit-metadata-json-ld-validator.p.rapidapi.com';
const KEY = process.env.RAPIDAPI_KEY;
const MIN_SCORE = 60;
const urls = process.argv.slice(2);
if (!KEY || urls.length === 0) {
console.error('Usage: RAPIDAPI_KEY=your_key node seo-check.mjs <url> [more urls...]');
process.exit(2);
}
let failed = false;
for (const url of urls) {
const res = await fetch(`https://${HOST}/v1/audit?url=${encodeURIComponent(url)}`, {
headers: { 'X-RapidAPI-Host': HOST, 'X-RapidAPI-Key': KEY },
});
const report = await res.json();
if (!res.ok) {
console.log(`✖ ${url}: ${report.error?.code ?? `HTTP ${res.status}`}`);
failed = true;
continue;
}
const { quality_score, indexability, canonical, structured_data } = report;
const problems = [];
if (quality_score.score < MIN_SCORE) problems.push(`score ${quality_score.score} is below ${MIN_SCORE}`);
if (!indexability.is_indexable) problems.push('page is not indexable');
if (!canonical.is_present) problems.push('canonical tag is missing');
if
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.