# 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), OR
- `site.canonicalUrl` is 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`):

<table id="bkmrk-field-type-purpose-h"><thead><tr><th>Field</th><th>Type</th><th>Purpose</th></tr></thead><tbody><tr><td>`hasWebsite`</td><td>`boolean?`</td><td>Explicit override: when false, forces no-website mode even if canonicalUrl is not empty</td></tr><tr><td>`gbpClaimed`</td><td>`boolean?`</td><td>Whether the business owner has claimed the GBP listing</td></tr><tr><td>`gbpManagerAccess`</td><td>`boolean?`</td><td>Whether ALAI/partner has been added as a manager to the GBP listing</td></tr></tbody></table>

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:

<table id="bkmrk-check-id-severity-ca"><thead><tr><th>Check ID</th><th>Severity</th><th>Category</th><th>Description</th></tr></thead><tbody><tr><td>`intake-not-submitted`</td><td>P1</td><td>evidence</td><td>Intake must be submitted or reviewed before workspace is review-ready</td></tr><tr><td>`gbp-first-strategy`</td><td>P1</td><td>local</td><td>**Strategy finding:** recommends GBP-first approach + optional simple-site later</td></tr><tr><td>`gbp-not-claimed`</td><td>P0</td><td>local</td><td>Business owner has not claimed the GBP listing → cannot manage or optimize</td></tr><tr><td>`gbp-manager-access-missing`</td><td>P1</td><td>local</td><td>ALAI/partner not added as manager → cannot perform optimization work</td></tr><tr><td>`gbp-claim-status-unknown`</td><td>P1</td><td>local</td><td>Claim/manager status not confirmed → action recommended to clarify</td></tr><tr><td>`gbp-nap-url-missing`</td><td>P1</td><td>local</td><td>GBP URL not recorded → NAP consistency cannot be verified</td></tr><tr><td>`gbp-primary-category-missing`</td><td>P2</td><td>local</td><td>Priority services missing → cannot determine correct GBP primary category</td></tr><tr><td>`gbp-hours-not-confirmed`</td><td>P2</td><td>local</td><td>Business hours not confirmed → can reduce customer trust</td></tr><tr><td>`gbp-photos-not-confirmed`</td><td>P2</td><td>local</td><td>Photos not confirmed → profiles with photos attract more engagement</td></tr><tr><td>`gbp-review-routine-not-confirmed`</td><td>P2</td><td>local</td><td>Review response routine not set → important trust/engagement signal</td></tr><tr><td>`gbp-posts-not-confirmed`</td><td>P2</td><td>local</td><td>GBP posts activity not confirmed → posts keep profile active and relevant</td></tr><tr><td>`missing-priority-services`</td><td>P2</td><td>content</td><td>Priority services missing → needed for page/backlog recommendations</td></tr><tr><td>`missing-competitors`</td><td>P2</td><td>content</td><td>Competitor list missing → needed for manual review context</td></tr><tr><td>`access-status-unknown`</td><td>P2</td><td>evidence</td><td>Analytics/Search Console access status unknown</td></tr></tbody></table>

**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 canonicalUrl
- `domainMatchCheck` — 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 `local` category 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-strategy` finding 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 `undefined` or 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.ts` lines 124-437
- **Types:** `src/lib/workspace/types.ts` lines 54-63
- **Fixture:** `scripts/validate-gbp-local.ts`
- **Validation:** `npm run validate:gbp-local` passes
- **Build:** `npm run type-check` and `npm run build` pass

## Summary

The SEO Readiness Portal now handles **two client profiles**:

1. **Website clients** (existing path) — 6 checks, website-dependent validation
2. **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.