Rebuilding a Service Page for AI Search Citation:
A Full GEO Implementation Record
How we rebuilt /services/geo-seo/ on asquaresolution.com for AI Overview positioning — passage engineering, schema co-reference chains, speakable markup, entity SEO foundations, and internal link architecture. Every claim in this document is verifiable against the deployed code.
Starting Condition: A Draft Page, a Wrong Slug, and 718 Posts Pointing Nowhere
Before this implementation, asquaresolution.com had a draft GEO service page with the slug services-geo-seo (WordPress auto-appended the parent slug because no parent page existed yet). There was no /services/ parent page. All internal CTAs — across 748 posts — linked to /services/, a page with no service architecture, no schema, and no AI-search-ready content structure.
The site’s main GEO content lived in three blog posts (IDs 8717, 25641, 17157) with strong topical authority but no connection to a service page. From an AI search perspective, there was no “entity” for the GEO service — just orphaned content and a draft page with the wrong URL.
Why this matters for AI citation: AI search systems construct their answers from structured entity relationships, not just crawled text. Without a coherent /services/geo-seo/ page linked from topical authority posts, with schema that co-references the site’s Organisation entity, the GEO service had no citation architecture.
What We Set Out to Build
- 1
A published
/services/parent page with correct schema hierarchy and service card architecture for all planned child services. - 2
A published
/services/geo-seo/page with passage-level GEO structure, complete JSON-LD schema, speakable markup, and AI citation-ready content architecture. - 3
Internal link normalisation: all 718+ posts pointing to
/services/updated to point to/services/— without 301 redirects. - 4
GEO cluster linkage: the three topical authority posts (8717, 25641, 17157) linked to
/services/geo-seo/with contextual service cards. - 5
Schema integrity: no
audienceTypearrays, no mismatched@idfragments, no currency errors, no duplicated BreadcrumbList definitions.
Implementation Approach: Staged, No-Redirect Architecture
The constraint was clear: no 301 redirects at any stage. Redirecting /services/ to /services/ before the new architecture was solid would damage any residual ranking signal. Instead, we used a staged parallel migration:
- 1
Create
/services/(published) and set/services/geo-seo/as a child with correct slug. - 2
Set canonical on
/services/pointing to/services/— a soft signal, not a redirect. - 3
Normalise all internal
/services/links to/services/via batched REST API updates. - 4
Add service cards linking from GEO cluster posts to
/services/geo-seo/.
The 301 redirect from /services/ to /services/ is a Phase 4 action, deferred until GSC data confirms the new architecture has been crawled and indexed.
Schema Architecture: Four Types, One Co-Reference Chain
The /services/geo-seo/ page deploys four JSON-LD schema types in a single @graph block, linked by @id co-references:
└ isPartOf → /#website
└ publisher → /#organization
└ breadcrumb → /services/geo-seo/#breadcrumb (reference only)
BreadcrumbList @id: /services/geo-seo/#breadcrumb
└ Home (pos 1) → asquaresolution.com
└ Services (pos 2) → /services/
└ GEO Services (pos 3) → /services/geo-seo/
Service @id: /services/geo-seo/#service
└ provider → /#organization
└ areaServed: [“GB”,”US”,”CA”,”AU”,”IE”]
└ offers: Offer (free audit, price:0, priceCurrency:”GBP”)
FAQPage @id: /services/geo-seo/#faqpage
└ 6 Question/Answer pairs (standalone, citable)
Fig. 1 — Schema @graph co-reference chain. All four types share the same /#organization entity via publisher/provider co-reference. The BreadcrumbList and FAQPage are standalone @graph nodes; WebPage references BreadcrumbList by @id only.
The speakable specification targets five CSS selectors: .gs-h1, .gs-hero-sub, .gs-faq-a, .gs-audit-headline, .gs-geo-definition. These correspond to the page elements most likely to be extracted as AI citation passages.
Passage Architecture: What Makes a Passage Citable
RAG (Retrieval-Augmented Generation) systems select passages based on semantic match and structural clarity. Our passage engineering criteria, derived from AI Execution Lab citation testing:
- ✔
Direct opening sentence: the first sentence must answer the implicit question without requiring context from surrounding text. “Entity SEO is the practice of…” not “As we discussed above…”
- ✔
Self-contained under 120 words: passages that require the reader to have read the preceding paragraph are not retrievable as standalone citations. Every key passage was written to function as an extracted excerpt.
- ✔
Entity named in the passage: “Generative Engine Optimization (GEO) is…” not “This service is…” — AI systems need explicit entity naming within the passage, not in surrounding context.
- ✔
Speakable-targeted: the definitional passage (
.gs-geo-definition) was structured as the single most citable definition on the page — 47 words, direct, entity-named.
Fig. 2 — Passage structure before and after GEO optimisation. The left panel fails all three RAG retrievability criteria. The right panel satisfies them: entity named in first sentence, self-contained at 47 words, direct opening with no context dependency.
Lab reference: Citation pattern testing for the passage structure criteria is documented at https://lab.asquaresolution.com/labs/2026-05-18-geo-entity-density-experiment
Documented Failures and Fixes
These are the actual failures encountered during this implementation. They are documented because understanding failure modes is more useful than a clean success narrative.
Failure 1: WordPress Slug Auto-Modification
When we created the GEO draft page with slug geo-seo before the /services/ parent page existed, WordPress silently changed the slug to services-geo-seo (appending the intended parent slug). The page went live at the wrong URL.
Fix: Created the /services/ parent page first (ID 25771), then set the GEO page’s slug to geo-seo with parent: 25771 in the same API call. WordPress then assigned the correct nested URL /services/geo-seo/.
Lesson: When creating child pages via the WordPress REST API, the parent page must exist before setting the child slug. Parent-first creation order is mandatory for correct URL assignment.
Failure 2: Rank Math Canonical Not Accessible via REST
Attempting to set _rank_math_canonical_url via the REST API meta field returned HTTP 200 but did not persist the value. The saved meta response contained only Astra theme keys — Rank Math’s meta fields are not registered for REST API access by default.
Fix: Manual wp-admin action documented as a blocker: Rank Math → Edit /services/ → Advanced tab → Canonical URL → https://asquaresolution.com/services/
Lesson: Rank Math meta fields require explicit REST API registration. Do not assume page meta is writable via REST without first confirming the registered fields for the specific plugin version.
Failure 3: CSS Unicode Escape in Python String
Writing content:'92' in a Python string produced content:'92' in the saved CSS. Python interpreted as an octal escape character (chr(2)), stripping the visible character and leaving only 92.
Fix: Double-escape in Python: content:'\2192' produces the literal string content:'92' in the CSS output. This applies to any CSS Unicode escape written inside a Python string literal.
Lesson: Python string escaping and CSS Unicode escaping interact. Always verify CSS arrow characters render correctly in live content — not just in the Python source.
Failure 4: Schema Validation False Negatives
Verification checks for BreadcrumbList position 2 URL and WebPage breadcrumb reference initially returned false negatives. The check strings contained regex-style wildcards (.*) used as plain string matches, which never evaluate as True regardless of content.
Fix: Replaced pattern-matching checks with re.findall() and re.search() calls. Confirmed correct content via direct GET requests with explicit pattern matching.
Pre-existing Blocker: legalName Typo in Knowledge Graph
The Rank Math Knowledge Graph had legalName: "cantact" (typo) instead of "A Square Solutions". This propagates through the Organization @id co-reference chain to all pages on the site — the entity name in structured data is incorrect site-wide.
Status: Manual fix required. Rank Math → Titles & Meta → Knowledge Graph → Organisation Name. Not fixed programmatically — requires admin UI access.
Structural Outcomes and What to Measure
The following structural outcomes are confirmed as of deployment date. Traffic and citation metrics will be measured at 30, 60, and 90 days post-deployment against the baselines established below.
| Outcome | Measurement | Status |
|---|---|---|
| /services/ hub page live | HTTP 200, indexed in GSC | Confirmed (ID 25771) |
| /services/geo-seo/ live at correct URL | HTTP 200, slug=geo-seo, parent=25771 | Confirmed (ID 25768) |
| 4 JSON-LD schema types deployed | Rich Results Test pass | Confirmed |
| 718 posts: internal links normalised | 0 remaining /services/ refs in posts | Confirmed (spot-check 30 posts) |
| GEO cluster posts linked to /services/geo-seo/ | Posts 8717, 25641, 17157 contain service card | Confirmed |
| Schema bugs resolved | audienceType, priceCurrency, @id fragments, BreadcrumbList deduplicated | Confirmed |
Metrics to Track at 30 / 60 / 90 Days
| Metric | Tool | Baseline |
|---|---|---|
| AI Overview appearances for “generative engine optimization services” | Manual Google search, SGE tracking | 0 at deploy date — page was draft |
| ChatGPT Search citations for GEO service queries | Manual ChatGPT Search sampling, 20-query set | 0 at deploy date |
| Perplexity citations for GEO queries | Manual Perplexity sampling, same 20-query set | 0 at deploy date |
| GSC Coverage: /services/geo-seo/ indexed | Google Search Console | Not yet indexed at deploy |
| GSC impressions for /services/geo-seo/ | Google Search Console → Performance | 0 at deploy date |
| Rich Results eligibility | Rich Results Test, Google Search Console → Enhancements | All 4 schema types pass Rich Results Test |
⚠ Remaining to Complete This Case Study
- Screenshot: Google Search Console coverage graph showing /services/geo-seo/ indexing status at 30 days
- Screenshot: First AI Overview or ChatGPT citation appearance for a GEO-related query
- Screenshot: Rich Results Test pass for all 4 schema types on live URL
- Data: GSC impressions/clicks for /services/geo-seo/ at 30/60/90 days
- Data: Citation count across 3 AI systems at 30/60/90 days vs. 0 baseline
- Fix: legalName typo must be resolved before Organization schema can be called fully correct
Tooling Used in This Implementation
WordPress REST API
Schema Markup Validator
Rich Results Test
Screaming Frog SEO Spider
Google Search Console
Claude API (passage QA)
Rank Math SEO
LiteSpeed Cache
Phased Delivery Timeline
| Phase 1 | Architecture Foundation | /services/ hub created, GEO page slug corrected, 6 schema bugs fixed, page published. Runtime: ~4 hours of implementation + ~66 min bulk post migration. |
| Phase 2 | Link Migration | 718 posts migrated via batched Python/REST (25/batch, 1.2s sleep). 7 pages updated. GEO cluster service cards appended. UK page updated. Total: ~70 minutes automated. |
| Phase 3 | Service Pages (Draft) | 4 draft child service pages created: entity-seo, technical-seo, ai-automation, ai-consulting. All with full schema, CSS, content architecture. |
| Trust Pass | Evidence & Methodology | Methodology sections, tooling stacks, limitations blocks, Lab integration added to all 5 service pages. |
| Phase 4 | Redirect (Pending) | /services/ → /services/ 301 redirect. Deferred until GSC confirms new architecture indexed. Estimated: Week 6–8 post-launch. |
What We’d Do Differently
Lesson 1
Create parent pages before children, always. WordPress’s slug auto-modification is silent and immediate. Any batch page creation script should verify parent existence and create the hierarchy top-down, never assuming WordPress will hold the intended slug for a child-to-be-attached page.
Lesson 2
Audit REST-accessible meta fields before assuming writeability. Plugin meta fields (Rank Math, SEOPress, etc.) are not automatically accessible via the WordPress REST API. Run a field discovery request against /wp/v2/pages/schema before any bulk meta operation to confirm which meta keys are registered.
Lesson 3
Validate schema @id chains top-down, not schema-type by schema-type. The BreadcrumbList deduplication error and audienceType array format were both caught by top-down chain validation — checking that every @id reference resolves to a valid defined entity in the same @graph. Type-by-type validation misses cross-reference errors.
Lesson 4
Idempotent operations are mandatory for any bulk content change. The skip-if-unchanged check prevented double-processing 30 posts that had been updated in an earlier partial run. Without idempotency, re-running a migration after a failure creates duplicate content or corrupted internal links.
Lesson 5
Passage architecture requires a structural criterion, not a length guideline. “Keep it short” is not an actionable passage specification. The criterion “first sentence must answer the implicit question without context from surrounding text” is actionable, testable, and produces consistently better citation candidates than word-count guidance alone.
Services Implemented in This Case Study
Also in This Implementation Series
