GBP/Local-First Audit Mode (No-Website Clients)
GBP/Local-First Audit Mode (No-Website Clients)
Implemented: MC #102861 (2026-06-03)
Driver: First real client Smoke House Hadžići (no website, GBP-only) via partner Asmir
Status: PASS — type-check, build, validate:phase4, validate:phase5, validate:gbp-local
Overview
The SEO Readiness Portal now supports clients who do not have a website and rely solely on Google Business Profile (GBP) as their primary online presence. This is a common scenario for small local businesses (restaurants, trades, services).
When a client is detected as no-website, the audit runner switches into GBP-first mode and runs a different checklist tailored to local optimization best practices.
Detection Logic
No-website mode is activated when:
intake.hasWebsite === false(explicit opt-in), ORsite.canonicalUrlis empty or blank (implicit)
The detection is implemented in src/lib/audit/runner.ts function isNoWebsiteMode(site, intake).
New Intake Fields (Optional, Non-Breaking)
Three new fields have been added to the Intake type (src/lib/workspace/types.ts):
| Field | Type | Purpose |
|---|---|---|
hasWebsite |
boolean? |
Explicit override: when false, forces no-website mode even if canonicalUrl is not empty |
gbpClaimed |
boolean? |
Whether the business owner has claimed the GBP listing |
gbpManagerAccess |
boolean? |
Whether ALAI/partner has been added as a manager to the GBP listing |
All three are optional and undefined-safe. Existing fixtures and validations are unaffected.
GBP-First Checklist (12 Checks)
When no-website mode is active, the audit runs the following checks instead of website-dependent checks:
| Check ID | Severity | Category | Description |
|---|---|---|---|
intake-not-submitted |
P1 | evidence | Intake must be submitted or reviewed before workspace is review-ready |
gbp-first-strategy |
P1 | local | Strategy finding: recommends GBP-first approach + optional simple-site later |
gbp-not-claimed |
P0 | local | Business owner has not claimed the GBP listing → cannot manage or optimize |
gbp-manager-access-missing |
P1 | local | ALAI/partner not added as manager → cannot perform optimization work |
gbp-claim-status-unknown |
P1 | local | Claim/manager status not confirmed → action recommended to clarify |
gbp-nap-url-missing |
P1 | local | GBP URL not recorded → NAP consistency cannot be verified |
gbp-primary-category-missing |
P2 | local | Priority services missing → cannot determine correct GBP primary category |
gbp-hours-not-confirmed |
P2 | local | Business hours not confirmed → can reduce customer trust |
gbp-photos-not-confirmed |
P2 | local | Photos not confirmed → profiles with photos attract more engagement |
gbp-review-routine-not-confirmed |
P2 | local | Review response routine not set → important trust/engagement signal |
gbp-posts-not-confirmed |
P2 | local | GBP posts activity not confirmed → posts keep profile active and relevant |
missing-priority-services |
P2 | content | Priority services missing → needed for page/backlog recommendations |
missing-competitors |
P2 | content | Competitor list missing → needed for manual review context |
access-status-unknown |
P2 | evidence | Analytics/Search Console access status unknown |
Total: 12 checks in no-website mode vs. 6 in standard website mode.
Skipped Website-Dependent Checks
The following checks are conditionally skipped in no-website mode:
httpsCanonicalCheck— requires canonicalUrldomainMatchCheck— requires canonicalUrl and domain
These are replaced by the GBP-specific checks above.
Report/Backlog/Export Flow
GBP-first findings flow through the existing report/backlog/export workflow with no changes:
- Findings are categorized (new
localcategory introduced) - Backlog conversion works as normal
- Markdown export includes all GBP findings
- No-ranking disclaimer is preserved
Validation Scripts
A new fixture script validates the no-website path:
npm run validate:gbp-local
This runs scripts/validate-gbp-local.ts which:
- Creates a test client with empty
canonicalUrl - Runs the local audit in no-website mode
- Asserts exactly 12 checks are run
- Confirms
gbp-first-strategyfinding is present
Existing validations remain unchanged and passing:
npm run validate:phase4— standard website path (6 checks)npm run validate:phase5— report generation
GBP API Integration (Deferred)
Important operator note: This is a manual-input MVP. The portal does not integrate with the Google Business Profile API to fetch live data (photos count, reviews count, hours, etc.).
All GBP checks rely on:
- Intake fields (
gbpClaimed,gbpManagerAccess,googleBusinessProfileUrl) - Intake notes (hours/photos/reviews confirmed via text patterns)
Live GBP API integration is a follow-on scope, likely in parallel with Google Search Console/Analytics integration (MC #102806 deferred).
Safe Defaults
All GBP checks follow a fail-closed philosophy:
- If a field is
undefinedor unknown → emit an "action recommended" finding (P1 or P2) - Never emit a false pass
Example: if gbpClaimed is undefined, the check emits gbp-claim-status-unknown (P1) asking the operator to confirm with the client.
Implementation Evidence
- Source:
src/lib/audit/runner.tslines 124-437 - Types:
src/lib/workspace/types.tslines 54-63 - Fixture:
scripts/validate-gbp-local.ts - Validation:
npm run validate:gbp-localpasses - Build:
npm run type-checkandnpm run buildpass
Summary
The SEO Readiness Portal now handles two client profiles:
- Website clients (existing path) — 6 checks, website-dependent validation
- No-website / GBP-only clients (new path) — 12 checks, GBP-first optimization
Detection is automatic based on canonicalUrl or explicit hasWebsite flag. Both paths use the same report/backlog/export workflow. No breaking changes to existing fixtures or validations.
No comments to display
No comments to display