Local SEO skill for Codex

Win the map pack without breaking Google's rules. Codex keeps one source of truth for every location's name, address, phone and hours and generates location pages and JSON-LD from it. It audits Business Profiles field by field against Google's guidelines, flags keyword-stuffed names and doorway location pages, fixes inconsistent citations, and sets up review requests that avoid gating and incentives.

  • Growth & SEO
  • $local-seo
  • 172 lines
  • 2 files
  • ~2,150 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- local-seo

Installs to ~/.agents/skills/local-seo/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $local-seo, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Improves local search visibility for businesses with physical locations or service areas — Google Business Profile setup and audit (name, categories, hours, services, photos), review acquisition and responses within policy, NAP consistency across citations, location and service-area pages, LocalBusiness JSON-LD, and tracking GBP traffic. Use when a business wants to show in the map pack or "near me" searches, has multiple branches, sees wrong info on Google Maps, or needs location pages built for a website.

Use it when

  • A business wants to appear in the map pack or near-me searches
  • Building or fixing location or service-area pages
  • Business details are wrong or inconsistent across Google, Apple and directories
  • Setting up a review request and response process

Use something else when

How to check the result

Each location's NAP matches the source file on GBP, the site and top citations; location pages validate with zero schema errors; GBP clicks show up in analytics under the UTM campaign.

The mistake it prevents

Adding service keywords and city names to the Business Profile name, which violates guidelines and commonly ends in suspension.

~/.agents/skills/local-seo/SKILL.md

--- name: local-seo description: Improves local search visibility for businesses with physical locations or service areas — Google Business Profile setup and audit (name, categories,… license: MIT ---

Done well: each real location has one verified, complete, policy-compliant Business Profile; the website has a genuinely useful page per location that matches the profile’s name, address and phone exactly; reviews arrive steadily from real customers; and GBP traffic is measurable in analytics.

How local ranking works

Google states local results are based on relevance (how well the profile matches the search), distance (from the searcher or the location in the query) and prominence (reviews, links, mentions, overall web presence). Distance cannot be optimized; relevance and prominence can. Paying Google does not affect local organic ranking.

Workflow

- [ ] 1. Inventory locations and the source of truth for NAP + hours
- [ ] 2. Audit and fix each Business Profile
- [ ] 3. Build or fix location pages and LocalBusiness markup
- [ ] 4. Align citations (NAP consistency)
- [ ] 5. Set up a compliant review program
- [ ] 6. Track GBP traffic and calls
- [ ] 7. Monitor monthly

1. Inventory

Create one table as the source of truth and use it everywhere (site, GBP, citations):

location_id,business_name,street,city,region,postal_code,country,phone,url,primary_category,hours,lat,lng
nyc-01,Acme Dental,"120 W 23rd St, Suite 4",New York,NY,10011,US,+1-212-555-0142,https://acme.example/locations/chelsea,Dentist,"Mo-Fr 08:00-18:00; Sa 09:00-13:00",40.7433,-73.9940

In a repo, check AGENTS.md and look for existing location data (CMS collection, JSON, database table) before creating a new one; location pages should be generated from it.

2. Business Profile audit

Edits to profiles happen in the Business Profile interface or API under the owner’s account; Codex prepares the changes and the user applies them (or approves API calls).

FieldRule
Business nameExactly the real-world name on signage and documents. Adding keywords or cities (“Acme Dental - Best Dentist NYC”) violates guidelines and risks suspension
Primary categoryThe most specific category describing the core business; the strongest relevance lever. Check which categories top-ranking competitors use
Secondary categoriesOnly those genuinely offered; a few, not dozens
Address / service areaStorefront: real address customers visit. Service-area business with no customer visits: hide address, set service areas (regions or cities, not a giant radius). No virtual offices or PO boxes
PhoneLocal number for the location; a tracking number is acceptable as primary if the main number is listed as additional
WebsiteThe matching location page, not the homepage, for multi-location brands; add UTM parameters (step 6)
HoursAccurate, plus special hours for holidays. Wrong hours generate negative reviews
Services/productsComplete, in the customer’s words, with descriptions
PhotosReal exterior (helps people find it), interior, team, work; refreshed periodically
DescriptionPlain description of what the business does; no links, no promotions, no keyword lists

One profile per location; one profile per practitioner only where guidelines allow (e.g. individual doctors), never duplicates. Merge or remove duplicates through support.

3. Location pages

One page per real location, generated from the source of truth, with content a visitor needs:

  • Name, full address, phone (clickable tel:), hours, embedded map or directions link.
  • What is offered at this location specifically: services, staff, languages, parking, accessibility, nearby landmarks, local photos.
  • Reviews or testimonials from this location’s customers (marked up only if shown).
  • Unique copy; city-name swaps of one template are doorway pages.
  • Linked from a store locator/index page with crawlable links, not only a JS map.

LocalBusiness JSON-LD on each page (use the most specific subtype):

{
  "@context": "https://schema.org",
  "@type": "Dentist",
  "@id": "https://acme.example/locations/chelsea#location",
  "name": "Acme Dental",
  "url": "https://acme.example/locations/chelsea",
  "telephone": "+1-212-555-0142",
  "image": "https://acme.example/img/chelsea-front.jpg",
  "address": { "@type": "PostalAddress", "streetAddress": "120 W 23rd St, Suite 4",
    "addressLocality": "New York", "addressRegion": "NY", "postalCode": "10011", "addressCountry": "US" },
  "geo": { "@type": "GeoCoordinates", "latitude": 40.7433, "longitude": -73.9940 },
  "openingHoursSpecification": [
    { "@type": "OpeningHoursSpecification", "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"], "opens": "08:00", "closes": "18:00" },
    { "@type": "OpeningHoursSpecification", "dayOfWeek": "Saturday", "opens": "09:00", "closes": "13:00" }
  ],
  "parentOrganization": { "@id": "https://acme.example/#org" }
}

Do not add aggregateRating from your own reviews about yourself; self-serving review markup is not eligible. Validate with schema-markup’s linter and the Rich Results Test.

Service-area businesses: one page per service the business offers, mentioning the areas served, plus a small number of area pages only where there is real area-specific content (local projects, regulations, photos, testimonials).

4. Citations and NAP consistency

  • Match the source of truth character for character where possible (Suite vs Ste. is fine; a different phone number or old address is not).
  • Priority order: Google Business Profile, Apple Business Connect, Bing Places, the main data aggregators in the country, Facebook, Yelp, and the top industry directories that rank for the business’s main queries.
  • Find inconsistencies by searching the old address and old phone number; fix the sources, not just the copies.
  • Moving or rebranding: update GBP first, then site, then citations; keep redirects.

5. Reviews within policy

  • Ask every customer, through the same channel, with a direct review link (from the profile’s “Ask for reviews” share link).
  • Never gate (asking only happy customers, or filtering via a satisfaction survey first), never offer incentives, never write or buy reviews, never have staff review. This violates Google’s policies and, in the US, the FTC rule on fake reviews.
  • Respond to reviews, especially negative ones: specific, calm, no private details (no confirming someone was a patient), offer an offline resolution path.
  • Steady flow beats bursts; sudden spikes can trigger filtering.

Drafting replies is fine; posting them on the user’s behalf requires their explicit confirmation of each reply.

6. Tracking

  • Website link in GBP with UTM tags so it is not lumped into organic: https://acme.example/locations/chelsea?utm_source=google&utm_medium=organic&utm_campaign=gbp-chelsea (keep utm_medium=organic if reporting must still count it as organic search; agree the convention with whoever owns analytics, see utm-attribution).
  • GBP Performance shows searches, views, calls, direction requests and website clicks per profile; export monthly.
  • Call tracking numbers: use as primary only with the real number as additional.

7. Monitor monthly

  • Profile edits suggested by users or Google (“Google updated your profile”) — review and reject wrong ones.
  • Rank checks for core queries from several points in the service area (grid-based rank trackers), not from one office desk.
  • Review count, rating, response rate per location.

Gotchas

  • Keyword-stuffed business names often rank short-term and then get suspended; competitor edits can expose them. Do not copy the tactic.
  • A suspended profile is reinstated through the reinstatement form with proof (signage photos, utility bills, business licence); do not create a new profile.
  • Changing many fields at once can trigger re-verification; batch carefully.
  • Coworking spaces and virtual offices typically fail verification and violate policy.
  • Store locators that render entirely in JS with no crawlable links hide every location page from crawlers.

Output

**Locations:** 12 (locations.csv as source of truth, used by /locations/[slug]).
**GBP fixes:** 3 names de-stuffed, primary category Dentist→Pediatric dentist for 2,
special hours added for Nov–Jan, website links now point to location pages with UTMs.
**Site:** 12 location pages with unique content blocks, Dentist JSON-LD (0 errors),
crawlable /locations index.
**Citations:** 9 listings with old Brooklyn phone found (list), fixed 6, 3 pending.
**Reviews:** request flow drafted (SMS + email, same link for all customers).

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Local SEO"
  short_description: "Win the map pack without breaking Google's rules"
  default_prompt: "$local-seo Audit our 12 dental clinics' Google Business Profiles and location pages"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
New

Introducing Codex Skills Pro

79 professional skills that take Codex through complete engagements, each with its own scripts, references and a report that verifies the result.

All-AccessOne-time payment, no subscription
$49
Get All-AccessOr browse individual skills from $2.99 →

Secure checkout by Creem