Local SEO audit of a location

Embed
Preview of the card
<a href="https://seolyticize.com/docs/ref-get-local-seo-audit"><img src="https://seolyticize.com/docs/_api/public/orgs/71cb2b7a-a719-4003-b3ea-6321dc1db8ab/spaces/3bf2dbf7-3faa-473c-ba3b-30588f5f8de4/pages/0c6e5a30-54bc-42bc-b991-57cf6a7f639f/social-card.svg?v=3e7ae33eec8b" alt="Local SEO audit of a location" width="600" height="315"></a>
POSThttps://seolyticize.com/api/v1/tools/get_local_seo_audit

Scores one location's local SEO 0–100 (a heuristic, said so in the answer) from six weighted parts, each check full, partial or low with the reason, or null when not measured — then left out and the other weights rescaled: the Google Business Profile (25: primary category against the homepage, about four secondary categories, posts, photos, Q&A, hours), reviews (20: at least 10, the rating, the last three months, six months' monthly flow and gaps over three weeks, owner response rate, and a fake-review flag when two of six patterns match), the site (20: city and service in the title and H1, visible NAP, a tel: link, a map embed, location pages over 60% unique by the city-swap test, gates at 30 and 50 location pages), NAP and citations (15, the check_nap_consistency comparison; directories: true adds the directory citations), LocalBusiness schema (10: a subtype, geo to five decimals, priceRange under 100 characters, a unique @id per location with branchOf) and links (10); plus a rating spread that leans to five stars, review gating, service pages, location pages within three clicks, hours on the site, trust badges, the PostalAddress parts, the subtype that fits the vertical, areaServed, retired VehicleListing and SpecialAnnouncement markup and, with duplicates, other listings at the same address or phone. gbpChecklist scores the 25-field profile checklist (2/1/0 per field, null where DataForSEO returns nothing — verified status, Q&A, videos, products, photo dates — weighted by vertical, banded 90/75/50/25); grid reads back the latest grid scan for the main service (share of local voice, visibility points, the worst quadrant, a heatmap); mapsHealth combines profile 25, grid 20, reviews 20, NAP 15, schema 10 and rival standing 10. Detects storefront, service-area business (which skips the map and address checks) or hybrid, and the vertical; adds listing completeness 0–100 and, with competitorRadiusKm, the competitors per km² in the primary category. Reviews come from sync_local_reviews; posts from a get_business_posts task passed as postsTaskId. Answers 'how good is our local SEO' and 'what should we fix first for the map pack'. useListing reads the live listing and its Q&A, and competitorRadiusKm one business search, all paid: quote with estimate_cost. Free with useListing false and competitorRadiusKm 0.

Parameters

Idempotency-Keystringheader
Any unique string, up to 200 characters. A retry with the same key and body is answered from the first answer (Idempotent-Replayed: true) for a day, so it never buys or writes twice; the same key with another body is refused.

Request body

application/json
clientIdstringrequired
locationIdstringrequired
useListingboolean
= true
postsTaskIdstring
A get_business_posts taskId for this listing; collecting it is free.
= null
competitorRadiusKmnumber
Radius for competitor density; 0 skips the paid business search.
= 5
directoriesboolean
= false
duplicatesboolean
Search the listings within 1 km for duplicates at this address or phone (one paid business search).
= false
citystring
= null
servicestring
= null
modelstring
auto | storefront | sab | hybrid = auto
maxCostMicrosinteger
Optional spending limit for this call, in micro-USD (1,000,000 = $1). A purchase that would take the call past it is refused before anything is bought. Pass the estimate from estimate_cost, or what the user agreed to spend.
dryRunboolean
True to buy nothing and get the quote instead: what the call would cost at most and what it would buy.
{
  "clientId": "string",
  "locationId": "string",
  "useListing": true,
  "postsTaskId": null,
  "competitorRadiusKm": 5,
  "directories": false,
  "duplicates": false,
  "city": null,
  "service": null,
  "model": "auto",
  "maxCostMicros": 0,
  "dryRun": true
}

Code samples

cURL
curl -X POST "https://seolyticize.com/api/v1/tools/get_local_seo_audit" \
  -H "Authorization: Bearer $SEOLYTICIZE_API_KEY" \
  -H "Idempotency-Key: <value>" \
  -H "Content-Type: application/json" \
  -d '{"clientId":"string","locationId":"string","useListing":true,"postsTaskId":null,"competitorRadiusKm":5,"directories":false,"duplicates":false,"city":null,"service":null,"model":"auto","maxCostMicros":0,"dryRun":true}'
TypeScript
Python
Go
PHP
Ruby
Java

Responses

200 The tool's result under data, and its meta.
Example
{
  "data": {},
  "meta": {
    "requestId": "string",
    "costMicros": 0,
    "cached": true,
    "cachedFrom": "string",
    "dataAsOf": "string",
    "sources": [
      "string"
    ],
    "partial": true,
    "next": [
      {
        "tool": "string",
        "args": {},
        "why": "string"
      }
    ],
    "nextCursor": "string",
    "dryRun": true
  }
}
Schema
datarequired
metaobjectrequired
Beside every answer: what it cost, whether it came from cache, how fresh it is, whether it is complete, and what to call next.
Show child parameters
requestIdstringrequired
costMicrosintegerrequired
Charged by this call, micro-USD (1,000,000 = $1).
cachedbooleanrequired
True when nothing was bought.
cachedFromstring
When the oldest cached answer used was bought.
dataAsOfstring
sourcesstring[]
partialbooleanrequired
True when the data is incomplete: a running crawl, unfinished days, unread pages.
nextobject[]required
Show child parameters
toolstring
argsobject
whystring
nextCursorstring
Pass as cursor for the next page.
dryRunboolean
Headers
X-RateLimit-Limitinteger
Requests this key may make per window.
X-RateLimit-Remaininginteger
Requests left in the current window.
X-RateLimit-Resetinteger
Seconds until the current window resets.
X-Request-Idstring
The id to quote about this request.
400 The body was not JSON or did not match the tool's input schema.
Example
{
  "error": "string",
  "code": "string",
  "next": "string",
  "requestId": "string"
}
Schema
errorstringrequired
A sentence written for the caller. Internal failures are reduced to 'The request could not be completed.' and never carry detail.
codestring
A stable snake_case reason to branch on; GET /api/v1/errors lists them all.
nextstring
The call or step that fixes it, when there is one.
requestIdstring
Quote it when asking about a failure.
Headers
X-RateLimit-Limitinteger
Requests this key may make per window.
X-RateLimit-Remaininginteger
Requests left in the current window.
X-RateLimit-Resetinteger
Seconds until the current window resets.
401 No key, or a key that is unknown or revoked.

Same as 400 · POST /api/v1/tools/get_local_seo_audit

Headers
WWW-Authenticatestring
403 The key's role does not permit the tool, or the key may not reach the named client.

Same as 400 · POST /api/v1/tools/get_local_seo_audit

Headers
X-RateLimit-Limitinteger
Requests this key may make per window.
X-RateLimit-Remaininginteger
Requests left in the current window.
X-RateLimit-Resetinteger
Seconds until the current window resets.
404 No tool by that name.

Same as 400 · POST /api/v1/tools/get_local_seo_audit

Headers
X-RateLimit-Limitinteger
Requests this key may make per window.
X-RateLimit-Remaininginteger
Requests left in the current window.
X-RateLimit-Resetinteger
Seconds until the current window resets.
409 A request with this Idempotency-Key is still running.

Same as 400 · POST /api/v1/tools/get_local_seo_audit

Headers
X-RateLimit-Limitinteger
Requests this key may make per window.
X-RateLimit-Remaininginteger
Requests left in the current window.
X-RateLimit-Resetinteger
Seconds until the current window resets.
422 A well-formed request the product declined, with the reason — a duplicate name, a plan limit, nothing configured to run.

Same as 400 · POST /api/v1/tools/get_local_seo_audit

Headers
X-RateLimit-Limitinteger
Requests this key may make per window.
X-RateLimit-Remaininginteger
Requests left in the current window.
X-RateLimit-Resetinteger
Seconds until the current window resets.
429 This key has used its window.

Same as 400 · POST /api/v1/tools/get_local_seo_audit

Headers
X-RateLimit-Limitinteger
Requests this key may make per window.
X-RateLimit-Remaininginteger
Requests left in the current window.
X-RateLimit-Resetinteger
Seconds until the current window resets.
Retry-Afterinteger
Seconds to wait before retrying.
500 The request could not be completed.

Same as 400 · POST /api/v1/tools/get_local_seo_audit

Headers
X-RateLimit-Limitinteger
Requests this key may make per window.
X-RateLimit-Remaininginteger
Requests left in the current window.
X-RateLimit-Resetinteger
Seconds until the current window resets.
Updated