SearchScore Agency Spec v2.1 merged

User Requirements & Technical Specification


Version: 2.1

Date: 2026-04-11

Author: Solution Architecture Review

Status: Merged Draft for Build Planning

Updated: Merges v1.1 (Google Doc) structural improvements into v2.0 agency spec




1. Executive Summary


SearchScore is an AI visibility optimisation platform. The Agency Subscription extends the core product to support marketing agencies, SEO consultants and freelancers who manage multiple client websites. Agencies need to demonstrate AI visibility gaps, deliver fixes and prove improvement over time, across all their clients from a single account.


The core product loop remains unchanged: Scan → Understand → Fix → Validate → Track. Every agency feature must support this loop. No scope expansion into social media, email marketing, CRM, campaign management, or generic SEO reporting.


Guiding Principles (non-negotiable)

1. Category focus at all costs - This is NOT an SEO tool, NOT a marketing suite, NOT a generic agency dashboard. It is a focused AI visibility system.

2. Commercially durable - Every architectural decision must support sustainable monetisation.

3. Operationally sane - Usage metering, entitlements, and cost controls are first-class requirements, not afterthoughts.

4. Platform-grade engineering - This is a platform rewrite, not a feature extension. Multi-tenancy, RBAC, queue architecture, and audit logging are structural, not optional.

5. Tool first, platform second - Build the best agency AI visibility tool in the market first. Only expose platform complexity where it increases revenue and defensibility.




2. User Personas


2.1 Primary: Agency Owner / Account Director

Role: Runs a digital marketing agency with 5-50 clients

Goal: Use AI visibility as a new service line or client retention tool

Pain: Needs to quickly show prospects why they're invisible to AI, then deliver measurable improvement

Behaviour: Wants branded reports, fast audits, and a way to manage multiple clients without switching accounts


2.2 Secondary: SEO Consultant / Freelancer

Role: Independent consultant managing 3-15 client sites

Goal: Add AI visibility audits to their service offering

Pain: Needs affordable multi-site access with professional output (reports, share links)

Behaviour: Runs audits during prospect calls, sends branded reports as follow-up


2.3 Tertiary: In-House Marketing Team

Role: Marketing manager overseeing multiple brand properties or subdomains

Goal: Monitor and improve AI visibility across the brand portfolio

Pain: Needs a single view of multiple properties with tracking over time

Behaviour: Weekly monitoring, monthly reporting to leadership




3. User Stories


3.1 Account Management

U-01 As an agency owner, I want to create a single account and manage all my clients under it, so I don't need separate logins

U-02 As an agency owner, I want to invite team members with role-based access (admin, analyst, viewer), so my team can work independently

U-03 As an agency owner, I want visibility into usage by team member, so I can understand who is consuming scans and costs


3.2 Client / Site Management

U-04 As an agency user, I want to add client domains to my workspace within my plan's allowance, so I can scale predictably

U-05 As an agency user, I want to organise clients into groups or folders (e.g. by industry, by account manager), so I can find them quickly

U-06 As an agency user, I want to see a single dashboard showing all client scores at a glance, so I can prioritise attention

U-07 As an agency user, I want to tag clients with custom labels (e.g. "at risk", "high opportunity", "onboarded"), so I can manage my pipeline

U-08 As an agency user, I want to assign a client to a specific team member, so responsibility is clear


3.3 Scanning & Auditing

U-09 As an agency user, I want to run a new scan on any client site from the dashboard, so I can get fresh data on demand

U-10 As an agency user, I want to trigger scans for multiple clients in bulk, so I don't have to do them one by one

U-11 As an agency user, I want to schedule automatic re-scans, so monitoring happens without manual effort

U-12 As an agency user, I want the scan to complete in under 60 seconds for a cached site, so I can run audits live on sales calls


3.4 AI Citation Engine

U-13 As an agency user, I want to see which AI queries mention my client and which don't, so I can identify content gaps

U-14 As an agency user, I want to add custom queries specific to my client's industry, so the citation data is relevant

U-15 As an agency user, I want to compare my client's citation rate against competitors, so I can quantify the gap

U-16 As an agency user, I want to see the actual AI response text, so I can show the client exactly what AI says about them and competitors


3.5 Fix Engine

U-17 As an agency user, I want to see a prioritised list of fixes for each client, sorted by impact, so I know what to tackle first

U-18 As an agency user, I want to mark fixes as in progress or completed, so I can track implementation status

U-19 As an agency user, I want to generate ready-to-implement assets (schema JSON-LD, llms.txt templates, robots snippets), so I can hand off to developers or implement myself

U-20 As an agency user, I want to see the estimated score improvement per fix, so I can prioritise the highest-value work


3.6 Competitor Tracking

U-21 As an agency user, I want to add 3-5 competitor domains per client, so I can benchmark performance

U-22 As an agency user, I want to see a side-by-side comparison of score, citations, and strengths/weaknesses, so I can explain the competitive landscape to clients

U-23 As an agency user, I want to see why a competitor is winning, so I can create a specific action plan


3.7 Reporting

U-24 As an agency user, I want to generate branded reports with my agency logo and colours, so the output looks professional when shared with clients

U-25 As an agency user, I want to export reports as PDF, so I can attach them to emails

U-26 As an agency user, I want to generate a shareable link for each report (with expiry and revoke), so clients can view results in a browser without logging in

U-27 As an agency user, I want before/after comparisons in reports, so I can demonstrate improvement over time

U-28 As an agency user, I want to generate a report for a prospect before they become a client, so I can use the audit as a sales tool

U-29 As an agency user, I want scheduled report delivery, so reporting can run on autopilot


3.8 White-Label

U-30 As an agency owner, I want to use a custom domain for client-facing pages, so clients see my brand

U-31 As an agency owner, I want client-facing pages to use my branding, so the output feels native to my agency

U-32 As an agency owner, I want to control whether "Powered by SearchScore" appears on client-facing outputs


3.9 Notifications & Alerts

U-33 As an agency user, I want to be notified when a client's score changes significantly, so I can respond proactively

U-34 As an agency user, I want to be notified when a new AI citation check shows a change in mention status, so I can update the client

U-35 As an agency user, I want email or Slack notifications for scan completions and scheduled reports, so nothing falls through the cracks


3.10 API & Integrations

U-36 As an agency user, I want API access to pull scan data into my own dashboards or tools, so I can integrate SearchScore into my workflow

U-37 As an agency user, I want to trigger scans via API, so I can build automated pipelines

U-38 As an agency user, I want webhook notifications for scan completion events, so my systems can react automatically


3.11 Usage & Billing

U-39 As an agency owner, I want to see usage by category (scans, citations, reports, API) for the current billing period, so I understand where value is being consumed

U-40 As an agency owner, I want to see approaching-limit warnings before hitting hard caps, so I'm not surprised

U-41 As an agency owner, I want to understand what higher plans or add-ons unlock, so I can decide when to upgrade




4. Functional Requirements


4.1 Account & Authentication


IDRequirementPriority
F-01Email/password authentication with optional SSO (Google, Microsoft)Must
F-02Role-based access control: Owner, Admin, Analyst, ViewerMust
F-03Team member invitation via email with role assignmentMust
F-04Password reset and session managementMust
F-05Two-factor authenticationShould
F-06Enterprise SSO supportCould
F-07All role restrictions enforced server-side at API level (not frontend-only)Must

4.2 Workspace & Site Management


IDRequirementPriority
F-08Single workspace per agency account containing all client sitesMust
F-09Add/remove client domains subject to plan entitlements and usage limitsMust
F-10Client grouping/folders with custom namesShould
F-11Custom tags per client siteShould
F-12Client assignment to team membersShould
F-13Bulk import of client domains via CSVShould
F-14Client search and filter by score range, tag, statusMust

4.3 Usage Metering & Entitlements


IDRequirementPriority
F-15Track scans used per organisation and billing periodMust
F-16Track citation queries used per organisation and billing periodMust
F-17Track report generations per organisation and billing periodMust
F-18Track API request volume per organisation and API keyMust
F-19Enforce plan entitlements and usage caps at API levelMust
F-20Expose current usage and remaining allowance in billing/settings UIMust
F-21Entitlement system configurable by plan (not hardcoded in business logic)Must
F-22Distinguish fresh scans vs cached scans in meteringMust
F-23Support for soft-limit warnings and hard-limit enforcementShould
F-24Support overage usage accounting for future billing integrationShould
F-25AI model call tracking by model for cost accountingShould

Entitlements to configure per plan:

• max_sites, max_scans_per_month, max_custom_queries_per_site, max_competitors_per_site

• max_team_members, report_generation_quota, api_enabled, webhook_enabled

• white_label_level (none / basic / advanced / full), custom_domain_enabled

• scheduling_frequency_allowed, citation_query_count, model_coverage


4.4 Scanning Engine


IDRequirementPriority
F-26On-demand scan for any client domainMust
F-27Scan completes in <60s for previously cached domainsMust
F-28Scan completes in <120s for new domainsMust
F-29Scheduled recurring scans (daily, weekly, monthly), subject to plan entitlementMust
F-30Bulk scan trigger (scan all / scan filtered group)Should
F-31Scan queue management (pause, cancel, prioritise)Could
F-32Scan history with full data retention (12 months minimum)Must
F-33Scan queue with job architecture: retries, dead-letter handling, per-org rate limitingMust
F-34Plan-based concurrency limits (one large agency must not starve others)Must
F-35Idempotent job executionMust

4.5 Scoring


IDRequirementPriority
F-36Overall AI Visibility Score 0-100 with tier labelsMust
F-37Sub-scores: Structure, Clarity, Authority, AccessibilityMust
F-38Score trend over time (line chart with selectable date range)Must
F-39Score comparison against industry averageShould
F-40Estimated improvement potential based on unresolved fixesMust

Tier Labels: Keep 5 tiers. Adopt naming: Invisible / Low Visibility / Emerging / Competitive / Dominant. Preserves existing data; "Dominant" aligns with aspirational agency positioning.


4.6 AI Citation Engine


IDRequirementPriority
F-41Predefined query set (10-20) per site, auto-generated from site content and industryMust
F-42Custom query addition per client site, subject to plan allowanceMust
F-43Citation check across supported models (MVP minimum 2, target 3)Must
F-44Multi-model citation checks configurable by plan or feature flagMust
F-45Per-query result: mention status, position, competitors mentioned, AI response snapshotMust
F-46Aggressive caching and reusable result windows where validMust
F-47Summary: "Mentioned in X of Y queries" with trendMust
F-48Competitor citation comparisonMust
F-49Insight generation: "Missing from queries related to [topic cluster]"Should
F-50Citation history over timeShould
F-51Optional deferred execution for less critical checksCould

4.7 Fix Engine


IDRequirementPriority
F-52Prioritised fix list sorted by impact (High/Medium/Low)Must
F-53Each fix includes: title, impact, effort, plain-English explanation, exact stepsMust
F-54Fix categories: Technical, Content, Entity/AuthorityMust
F-55Fix status tracking: Not Started / In Progress / Completed, with owner fieldMust
F-56Generated assets: schema JSON-LD, llms.txt template, robots.txt snippetsMust
F-57Estimated score gain per fix (clearly labelled as estimate, not guaranteed)Must
F-58"Re-scan after fix" button to validate improvementMust
F-59Fix history/change log per siteMust
F-60Data model must not block future: comments, client approval state, team handoffShould

4.8 Competitor Module


IDRequirementPriority
F-61Add up to 5 competitor domains per client site, subject to planMust
F-62Side-by-side score comparisonMust
F-63Citation rate comparisonMust
F-64Signal gap analysis: "Competitor has X, you don't"Must
F-65Competitive insight: "Why they're being recommended instead of you"Must
F-66Competitor score history over timeShould

4.9 Reporting


IDRequirementPriority
F-67Executive summary report (score + top issues + recommendation)Must
F-68Full diagnostic report (all sub-scores + all fixes + citation data)Must
F-69Competitor comparison reportShould
F-70Before/after progress reportMust
F-71PDF exportMust
F-72Shareable link with configurable expiry and revoke supportMust
F-73Share links must never expose internal operational metadataMust
F-74Branded reports (agency logo, colours, custom footer)Must
F-75Multiple report templates for different use casesShould
F-76Scheduled report generation and email deliveryShould
F-77Lead-gen audit report (for prospects, before they become clients)Must
F-78Prospect-safe report mode (no internal data leakage)Must

4.10 White-Label (Tiered, Client-Facing Only)


White-label applies to client-facing surfaces only: reports, share pages, optional custom domains. Internal agency workspace UI remains SearchScore-branded unless explicitly enabled for enterprise plans.


White-label is NOT an all-or-nothing toggle. Three independent levels, enabled by plan and feature flag:


Level 1: Basic Branding

IDRequirementPriorityPlan
F-79Agency logo on reports and share pagesMustAgency
F-80Primary/secondary colour customisationMustAgency
F-81"Powered by SearchScore" footer toggleShouldAgency

Level 2: Advanced Branding

IDRequirementPriorityPlan
F-82Custom domain (CNAME) for client-facing pagesShouldAgency Plus
F-83Branded report pages with full visual controlShouldAgency Plus
F-84Removal of SearchScore attribution on external surfacesShouldAgency Plus

Level 3: Full White-Label

IDRequirementPriorityPlan
F-85Custom email sender for scheduled reportsCouldAgency Plus
F-86Near-invisible SearchScore presence on all client-facing surfacesCouldAgency Plus

4.11 Notifications & Alerts


IDRequirementPriority
F-87Email notification on scan completion (default on, digestible)Must
F-88Alert on score change above configurable threshold (default on)Should
F-89Alert on citation status change (default off)Should
F-90Per-channel notification preferencesShould
F-91In-app notification centreShould
F-92Slack integration (lightweight, not core MVP unless trivial)Could

Principle: Do not build a spam machine. Default notifications must be limited and meaningful. Do not overinvest here before core usage is proven.


4.12 API (Premium Platform Layer)


API access must be entitlement-driven and support separate monetisation from dashboard seats.


IDRequirementPriority
F-93REST API with API key authenticationMust
F-94Separate API permissions from dashboard accessMust
F-95Separate API usage tracking and rate limitsMust
F-96Endpoints: list sites, trigger scan, get scan results, get fixes, get citationsMust
F-97Webhook registration for scan completion eventsShould
F-98API rate limiting enforced per organisation and per key (plan-based)Must
F-99API documentation (OpenAPI/Swagger)Must
F-100Architectural support for: bundled API for higher plans, standalone paid add-on laterMust



5. Non-Functional Requirements


5.1 Performance

IDRequirement
NFR-01Dashboard loads in <2 seconds after scan
NFR-02First scan completes in <120 seconds
NFR-03Cached scan returns in <60 seconds
NFR-04PDF report generation in <10 seconds
NFR-05API response time <500ms for non-scan data endpoints

5.2 Scalability

IDRequirement
NFR-06Support 500+ client sites per agency account
NFR-07Support 50+ concurrent scan requests across the platform with per-org controls
NFR-08Score history retained for 24 months
NFR-09Citation snapshots retained for 12 months

5.3 Security

IDRequirement
NFR-10All data encrypted at rest (AES-256) and in transit (TLS 1.3)
NFR-11API keys hashed, never stored in plaintext
NFR-12Session tokens expire after 24 hours or per security policy
NFR-13Role-based access enforced at API level for every endpoint
NFR-14Audit log for administrative and sensitive actions
NFR-15Strong tenancy enforcement - org A cannot access org B's data

5.4 Availability

IDRequirement
NFR-1699.5% uptime target for dashboard
NFR-17Scan queue resilient to individual failures (retry logic, dead-letter handling)
NFR-18Graceful degradation: dashboard shows last cached data if scan service unavailable

5.5 Platform Architecture

IDRequirement
NFR-19Clear service boundaries between SaaS layer and scan engine
NFR-20Idempotent job handling for all async operations
NFR-21Entitlement checks at API level for every request
NFR-22Usage instrumentation on every billable event



6. Data Model


6.1 Entity Relationship Overview


Organisation (1) ──< (M) User
Organisation (1) ──< (M) ClientSite
Organisation (1) ──< (M) ApiKey
Organisation (1) ──< (M) WebhookDelivery
Organisation (1) ──< (1) BrandingConfig
Organisation (1) ──< (M) UsageEvent
Organisation (1) ──< (M) AuditLog
ClientSite (1) ──< (M) Scan
ClientSite (1) ──< (M) Competitor
ClientSite (1) ──< (M) CustomQuery
ClientSite (1) ──< (M) Report
Scan (1) ──< (M) CitationResult
Scan (1) ──< (M) FixItem

6.2 Core Tables


organisations

ColumnTypeNotes
idUUIDPrimary key
nameVARCHAR(255)Agency name
planENUMpro, agency, agency_plus
billing_emailVARCHAR(255)
stripe_customer_idVARCHAR(255)
created_atTIMESTAMP
settings_jsonJSONBFeature flags, overrides

users

ColumnTypeNotes
idUUIDPrimary key
org_idUUIDFK -> organisations
emailVARCHAR(255)Unique
password_hashVARCHAR(255)bcrypt
roleENUMowner, admin, analyst, viewer
nameVARCHAR(255)
avatar_urlTEXT
last_loginTIMESTAMP
created_atTIMESTAMP

client_sites

ColumnTypeNotes
idUUIDPrimary key
org_idUUIDFK -> organisations
domainVARCHAR(255)Normalised domain
nameVARCHAR(255)Client display name
industryVARCHAR(100)
assigned_user_idUUIDFK -> users (nullable)
tagsTEXT[]PostgreSQL array
folderVARCHAR(255)Grouping
scan_scheduleJSONB{"frequency": "weekly", "day": "monday"}
created_atTIMESTAMP

competitors (separate table for clean normalisation)

ColumnTypeNotes
idUUIDPrimary key
site_idUUIDFK -> client_sites
domainVARCHAR(255)
labelVARCHAR(255)Display name
created_atTIMESTAMP

custom_queries (separate table for clean normalisation)

ColumnTypeNotes
idUUIDPrimary key
site_idUUIDFK -> client_sites
queryTEXT
created_byUUIDFK -> users (nullable)
created_atTIMESTAMP

scans

ColumnTypeNotes
idUUIDPrimary key
site_idUUIDFK -> client_sites
triggered_byENUMmanual, scheduled, api, bulk
triggered_by_user_idUUIDFK -> users (nullable)
statusENUMqueued, running, completed, failed
overall_scoreINTEGER0-100
tierVARCHAR(50)
structure_scoreINTEGER0-100
clarity_scoreINTEGER
authority_scoreINTEGER
accessibility_scoreINTEGER
category_scoresJSONBFull breakdown
issues_jsonJSONBAll detected issues
improvement_potentialINTEGEREstimated max score gain
fresh_scanBOOLEANTrue if new crawl, false if cached
duration_msINTEGER
started_atTIMESTAMP
completed_atTIMESTAMP
created_atTIMESTAMP

citation_results

ColumnTypeNotes
idUUIDPrimary key
scan_idUUIDFK -> scans
queryTEXTThe AI prompt tested
modelVARCHAR(50)chatgpt, perplexity, gemini
mentionedBOOLEAN
positionINTEGER1st, 2nd, etc. (null if not mentioned)
competitors_mentionedTEXT[]
response_snapshotTEXTAI response text
cachedBOOLEANTrue if reused from prior check
created_atTIMESTAMP

fix_items

ColumnTypeNotes
idUUIDPrimary key
site_idUUIDFK -> client_sites
scan_idUUIDFK -> scans (source scan)
titleVARCHAR(255)
categoryENUMtechnical, content, entity
impactENUMhigh, medium, low
effortENUMlow, medium, high
explanationTEXTWhy it matters (plain English)
stepsJSONBArray of step objects
generated_assetTEXTCode/template to copy
estimated_gainINTEGEREstimated score points (labelled as estimate)
statusENUMnot_started, in_progress, completed
owner_user_idUUIDFK -> users (nullable)
completed_atTIMESTAMP
change_historyJSONBArray of status change events
created_atTIMESTAMP

reports

ColumnTypeNotes
idUUIDPrimary key
site_idUUIDFK -> client_sites
typeENUMexecutive, diagnostic, competitor, progress, lead_gen
from_scan_idUUIDFK -> scans
to_scan_idUUIDFK -> scans (for progress reports, nullable)
share_tokenVARCHAR(255)For shareable links
share_expires_atTIMESTAMPConfigurable expiry
share_revokedBOOLEANSupport for revocation
pdf_urlTEXTCDN URL
brandedBOOLEAN
template_idVARCHAR(50)Report template identifier
created_atTIMESTAMP

branding_configs

ColumnTypeNotes
idUUIDPrimary key
org_idUUIDFK -> organisations (1:1)
levelENUMnone, basic, advanced, full
logo_urlTEXT
primary_colourVARCHAR(7)Hex
secondary_colourVARCHAR(7)Hex
font_familyVARCHAR(100)
custom_domainVARCHAR(255)CNAME
domain_verifiedBOOLEAN
show_powered_byBOOLEANDefault true
email_senderVARCHAR(255)Custom sender (full white-label only)
created_atTIMESTAMP

api_keys

ColumnTypeNotes
idUUIDPrimary key
org_idUUIDFK -> organisations
key_hashVARCHAR(255)SHA-256 of API key
key_prefixVARCHAR(8)First 8 chars for identification
nameVARCHAR(100)User-given name
permissionsTEXT[]Scopes (separate from dashboard access)
scopesTEXT[]API-specific scopes
last_used_atTIMESTAMP
created_atTIMESTAMP

usage_events

ColumnTypeNotes
idUUIDPrimary key
org_idUUIDFK -> organisations
user_idUUIDFK -> users (nullable)
typeVARCHAR(100)scan, citation, report, api_request, webhook, share_view
quantityINTEGERUsually 1
metadata_jsonJSONB{"fresh": true, "model": "chatgpt", "site_id": "..."}
billing_periodVARCHAR(20)"2026-04" format
created_atTIMESTAMP

entitlements (plan limits as data, not code)

ColumnTypeNotes
planVARCHAR(50)Primary key
max_sitesINTEGER
max_scans_per_monthINTEGER
max_citation_queries_per_siteINTEGER
max_custom_queries_per_siteINTEGER
max_competitors_per_siteINTEGER
max_team_membersINTEGER
report_quota_per_monthINTEGER
api_enabledBOOLEAN
api_rate_limit_per_hourINTEGER
webhook_enabledBOOLEAN
white_label_levelENUMnone, basic, advanced, full
custom_domain_enabledBOOLEAN
scheduling_frequenciesTEXT[]["weekly"], ["daily"], etc.
citation_modelsTEXT[]["chatgpt", "perplexity"], etc.

audit_logs

ColumnTypeNotes
idUUIDPrimary key
org_idUUIDFK -> organisations
actor_user_idUUIDFK -> users (nullable)
actionVARCHAR(255)
target_typeVARCHAR(100)
target_idUUIDNullable
metadata_jsonJSONB
created_atTIMESTAMP

webhook_deliveries

ColumnTypeNotes
idUUIDPrimary key
org_idUUIDFK -> organisations
webhook_idUUID
event_typeVARCHAR(100)
payload_hashVARCHAR(255)
statusVARCHAR(50)pending, delivered, failed
attemptsINTEGER
last_attempt_atTIMESTAMP
response_codeINTEGERNullable
created_atTIMESTAMP



7. Data Ownership Boundaries


Explicit split between systems. No dual ownership.


SaaS Database (PostgreSQL) owns:

• Organisations, users, permissions, RBAC

• Client sites, tags, folders, assignments

• Competitors, custom queries

• Branding configs, API keys, webhooks

• Reports, share tokens

• Fix status, fix history, fix owners

• Usage events, entitlements, billing state

• Audit logs, notification settings

• Webhook delivery records


Scan System (existing sites.db) owns:

• Raw scan execution, timing, duration

• Raw analysis output (scores, issues, category data)

• Citation run results and AI response snapshots

• Scan artifacts (cached pages, extracted text)

• Scan queue state


Interface: Scan outputs are normalised and persisted into the SaaS layer via a defined write boundary. Scan system produces results; SaaS system consumes and stores them. No shared mutable state.




8. API Structure


8.1 Authentication

POST   /api/auth/login
POST   /api/auth/register
POST   /api/auth/refresh
POST   /api/auth/forgot-password
POST   /api/auth/reset-password

8.2 Organisation & Users

GET    /api/org
PATCH  /api/org
GET    /api/org/users
POST   /api/org/users/invite
PATCH  /api/org/users/:id
DELETE /api/org/users/:id

8.3 Usage & Billing

GET    /api/org/usage                     # Current period usage summary
GET    /api/org/usage/summary             # Aggregated usage stats
GET    /api/org/usage/by-category         # Breakdown by type
GET    /api/org/usage/history             # Historical usage by period
GET    /api/org/entitlements              # Current plan limits

8.4 Client Sites

GET    /api/sites                         # List all client sites (paginated, filterable)
POST   /api/sites                         # Add client site (entitlement check)
GET    /api/sites/:id                     # Get site details
PATCH  /api/sites/:id                     # Update site
DELETE /api/sites/:id                     # Remove site
POST   /api/sites/import                  # Bulk CSV import
GET    /api/sites/:id/summary             # Quick summary (latest scan, score, tier)

8.5 Scans

POST   /api/sites/:id/scans               # Trigger scan (usage metered)
POST   /api/scans/bulk                    # Trigger bulk scan
GET    /api/sites/:id/scans               # Scan history
GET    /api/scans/:id                     # Full scan results
GET    /api/scans/:id/compare             # Compare two scans

8.6 Citations

GET    /api/sites/:id/citations           # Latest citation results
POST   /api/sites/:id/queries             # Add custom query (metered)
DELETE /api/sites/:id/queries/:qid        # Remove custom query
GET    /api/citations/:id/response        # Full AI response snapshot

8.7 Fixes

GET    /api/sites/:id/fixes               # List fixes (filterable by status, category)
PATCH  /api/fixes/:id                     # Update fix status/owner
GET    /api/fixes/:id/asset               # Get generated asset (schema, llms.txt etc)
POST   /api/fixes/:id/rescan              # Re-scan after fix

8.8 Competitors

GET    /api/sites/:id/competitors         # List competitors
POST   /api/sites/:id/competitors         # Add competitor (entitlement check)
DELETE /api/sites/:id/competitors/:cid
GET    /api/sites/:id/comparison          # Side-by-side comparison data

8.9 Reports

POST   /api/sites/:id/reports             # Generate report (usage metered)
GET    /api/sites/:id/reports             # List reports
GET    /api/reports/:id                   # View report
GET    /api/reports/:id/pdf               # Download PDF
POST   /api/reports/:id/share             # Create share link (with expiry)
DELETE /api/reports/:id/share             # Revoke share link
GET    /api/shared/:token                 # Public share page (no auth)

8.10 Branding

GET    /api/org/branding                  # Get branding config
PATCH  /api/org/branding                  # Update branding (level-gated)
POST   /api/org/branding/verify-domain    # Verify custom domain

8.11 API Keys

GET    /api/org/api-keys                  # List API keys
POST   /api/org/api-keys                  # Create key
DELETE /api/org/api-keys/:id              # Revoke key

8.12 Webhooks

GET    /api/org/webhooks                  # List webhooks
POST   /api/org/webhooks                  # Register webhook
DELETE /api/org/webhooks/:id              # Remove webhook

8.13 Notifications

GET    /api/notifications                 # List notifications
PATCH  /api/notifications/:id             # Mark read
GET    /api/org/notification-settings     # Get notification preferences
PATCH  /api/org/notification-settings     # Update preferences



9. UI Screen Specification


9.1 Navigation (Agency Mode)


Left sidebar:

Overview - Agency-wide dashboard

Clients - Client site list and management

[Client Name] - Expanded client submenu (when a client is selected):

- Dashboard

- Visibility Score

- AI Mentions

- Fixes

- Competitors

- Reports

Settings - Account, team, branding, API, billing


9.2 Agency Overview Dashboard


Purpose: Single view of all client health. Must answer: What's happening? Why? What do I do next?


Layout:

• Row 1: Agency summary stats

- Total clients, Average score across all clients

- Clients needing attention (score dropped >5 pts or below Emerging)

- Scans run this month / allowance remaining (with approaching-limit visual)

• Row 2: Client score table (sortable, filterable)

- Columns: Client name, Domain, Score, Tier, Trend (delta), Last scan, Status tags

- Click row -> navigate to client dashboard

- Inline "Run scan" button per row

• Row 3: High-priority alerts

- Score drops >5 points, New issues detected, Citation status changes

• Row 4: Usage summary

- Scans used/remaining, Citation usage, Reports generated, API calls


9.3 Client Dashboard (per-site)

• Hero score card

• Recommendation status card

• Opportunity card

• Top 3 fixes

• Competitor snapshot

• Recent scan changes

• AI mentions snapshot


9.4 Client Visibility Score Screen

• Overall score with trend

• 4 sub-score cards: Structure, Clarity, Authority, Accessibility

• Accordion detail per category: score, what's wrong, why it matters, related fixes


9.5 Client AI Mentions Screen

• Summary bar: mentioned in X/Y queries, best/worst topic clusters

• Table: Query, Model, Mention status (chip), Competitors, View response button

• Right-side drawer for AI response snapshot with highlighted mentions

• Insight panel: topic gaps, competitor dominance patterns


9.6 Client Fixes Screen

• Top summary: total issues, high-impact count, estimated score gain (labelled as estimate)

• Two-pane layout:

- Left: prioritised fix queue with status badges and owner

- Right: fix detail panel (title, why it matters, what to do, generated asset, action buttons)


9.7 Client Competitors Screen

• Score comparison table (you vs competitors)

• Citation rate comparison

• Insight panel: "Competitor A is winning because..."

• CTA: "View detailed comparison report"


9.8 Client Reports Screen

• Generate report button (select type + date range)

• Report list with type, date, status

• Actions: View, Export PDF, Share link (with expiry control), Delete


9.9 Client Management (List)

• Search bar

• Filters: tag, score range, folder, assigned user

• Bulk actions: scan selected, add tag, assign to user

• Each row: name, domain, score chip, tags, last scan, actions


9.10 Settings

• Account settings (org name, billing email)

• Team management (invite, roles, remove)

• Branding (logo upload, colour picker, custom domain - level-gated)

• API keys (create, view prefix, revoke)

• Webhooks (register URL, select events)

• Notification preferences

• Billing (plan, usage, Stripe portal link)

• Usage dashboard (scans, citations, reports, API by category)


9.11 Monetisation Visibility

The product should tastefully show economic value:

• Usage remaining indicators

• What higher plans unlock (inline, not pushy)

• When bulk scanning or API would be valuable

• Report branding locked behind plan

• Custom domain as premium feature

• This is not dark-pattern upselling - it's helping agencies understand upgrade value




10. Pricing Model (Backend Support)


10.1 Three-Layer Pricing Structure


The backend must support this structure, even if initial launch uses flat tiers:


Layer 1: Core Subscription

• Workspace, team, included sites, included scans, included reporting


Layer 2: Usage Layer

• Overage scans, citation expansions, high-volume API usage

• Metered and visible


Layer 3: Premium Add-ons

• API / MCP access

• Advanced white-label

• Custom domain


10.2 Reference Tiers


FeaturePro (£49/mo)Agency (£149/mo)Agency Plus (£299/mo)
Sites325100 included
Scans/month505002,000 included
Competitors/site255
Team members1525
Reports/month10100500 included
Branded reportsNoYesYes
White-label domainNoNoYes
API accessNoOptional add-onYes or add-on
WebhooksNoOptional add-onYes or add-on
Scheduled scansWeeklyDailyDaily
Citation queries/site102050
Custom queries/site520100 included
PDF exportYesYesYes
Share links/month10100500 included
Priority supportNoYesYes

Note: Public pricing can use "fair use" language if desired, but internal entitlement architecture must not depend on true unlimited usage. Every "included" tier has an internal hard cap with overage accounting.




11. Implementation Layers


Implementation is split into four product layers. Each layer is a coherent deliverable. Do not start a layer until the previous one is validated.


Layer A: Agency Workspace Core (Weeks 1-3)

The foundation. Multi-tenant data model, auth, client management.


• Multi-tenant SaaS database (PostgreSQL)

• Organisations, users, RBAC (server-side enforced)

• Client site CRUD (add, edit, remove, list, group)

• Entitlement system with plan-defined limits

• Usage metering foundation on every billable event

• Agency overview dashboard (all-clients view)

• Team member invitation with role assignment

• Basic scan scheduling

• JWT authentication, session management


Layer B: Core Product Experience (Weeks 4-6)

The value engine. Scores, fixes, citations, competitors.


• Client dashboard (per-site overview)

• AI Visibility Score breakdown

• AI Citation Engine (predefined queries, 2-model MVP, response snapshots)

• Fix Engine (prioritised list, status tracking, owner, generated assets, change history)

• Competitor module (add competitors, side-by-side comparison, gap analysis)


Layer C: Agency Tooling (Weeks 7-9)

The commercial output. Reports, branding, notifications, bulk operations.


• Report generation (executive, diagnostic, progress, lead-gen)

• PDF export

• Share links with expiry and revoke

• Branded reports (Level 1 white-label)

• Lead-gen prospect audit reports

• Bulk scan triggers

• Notification system (email alerts for score changes, scan completions)

• Usage dashboard in settings

• Monetisation visibility (approaching limits, plan upgrade hints)


Layer D: Platform Layer (Weeks 10-12)

The extensibility. API, webhooks, advanced white-label. Only after demand is proven.


• Custom domain support (CNAME verification)

• Advanced white-label (Level 2-3)

• REST API with key authentication (separate permissions, separate metering)

• API documentation (Swagger/OpenAPI)

• Webhook registration and delivery

• Scheduled report email delivery

• 3-model citation expansion

• Custom query metering as premium resource

• Slack notification integration

• Overage billing support




12. Technical Architecture


12.1 Current Stack (What Exists)

Backend: Node.js / Express on port 3470

Database: SQLite (`sites.db`) via better-sqlite3

Frontend: Static HTML served via Cloudflare Pages (`searchscore/landing/`)

Auth: None (public audit tool with admin panel behind password)

Payments: Stripe (price IDs configured, webhook live)


12.2 Required Architecture Changes


This is a platform rewrite, not a feature extension. Architectural decisions must reflect that.


Authentication Layer:

• JWT-based auth with refresh tokens

• Server-side RBAC enforcement on every endpoint

• Audit logging for admin actions


Database:

• PostgreSQL for SaaS data (users, orgs, clients, reports, fixes, usage, entitlements)

• Keep existing `sites.db` for raw scan data with explicit ownership boundary

• Turso/libSQL acceptable only if concurrency and migration strategy are explicit

• No dual ownership of scan results


Frontend:

• React/Next.js SPA for authenticated agency app

• Public landing page stays on Cloudflare Pages

• Agency app on `app.searchscore.io`


Job Queue:

• Redis/BullMQ with: retries, dead-letter handling, per-org concurrency limits

• Plan-based queue priority

• Idempotent job execution

• Cancellation support


Report Generation:

• Server-side PDF via Playwright

• Template engine for branded reports

• CDN-backed storage (R2)


Billing/Usage Layer:

• Entitlement service (reads from entitlements table, not hardcoded)

• Usage tracking on every billable event

• Quota enforcement at API level

• Plan-aware access checks


12.3 Infrastructure


Cloudflare CDN
  +-- searchscore.io (landing page, static)
  +-- app.searchscore.io (agency SPA)
        |
API Gateway (Express)
  +-- /api/auth/*   (authentication, RBAC enforcement)
  +-- /api/sites/*  (client management, entitlement checks)
  +-- /api/scans/*  (scan orchestration, usage metering)
  +-- /api/reports/* (report generation, usage metering)
  +-- /api/v1/*     (public API, separate auth, separate metering)
        |
   +----------+----------+
   |                     |
SaaS DB (PostgreSQL)  Scan Engine (existing)
Users, Orgs,          sites.db
Clients, Reports,     Raw scan execution
Fixes, Usage,         Citation runs
Entitlements          Scan artifacts
BrandConfig           Queue state
   |                     |
   +----------+----------+
              |
Job Queue (Redis/BullMQ)
  +-- Scan jobs (on-demand, scheduled, bulk)
  +-- Report generation jobs
  +-- Citation check jobs
  +-- Webhook delivery jobs
  +-- Per-org rate limiting & concurrency



13. Risks & Open Questions


13.1 Open Questions

1. Final tier naming model - Adopt Competitive/Dominant or keep Strong/AI-Ready?

2. Database strategy: PostgreSQL now (recommended), or Turso/libSQL for faster initial delivery?

3. Existing users: How do current Stripe subscribers (Full Report, Monitor) map to new plan structure?

4. Scan cost per model: Citation checks across 3 AI models x 20 queries = 60 API calls per scan. Cost model?

5. Custom domain support burden: DNS verification via CNAME requires agency IT cooperation. Start in Layer D only.

6. White-label leak prevention: What audit process ensures SearchScore identity never leaks on full white-label?

7. API pricing: Should API be bundled into Agency Plus or sold as a standalone add-on?

8. White-label split: Should white-label be split into branding, branded share pages, and custom domain as separate entitlements?

9. Usage pooling: Should scheduled scans and high-volume citation checks consume pooled usage credits?

10. Overage billing: Stripe metered billing integration - implement in Layer D or defer?


13.2 Risks

RiskImpactMitigation
Scan queue overload from bulk scansHighPer-org rate limiting, plan-based concurrency, staggered queue
AI API costs at scaleHighAggressive caching, plan-based query/model limits, usage metering
SQLite concurrency in multi-user SaaSHighLayer A must migrate to PostgreSQL
API cannibalises dashboard valueMediumEntitlement-based API, separate usage metering, possible add-on pricing
Scope creep into SEO/marketingMediumStrict backlog grooming against core loop
One agency degrading others' performanceHighQueue isolation, plan-based priority
White-label identity leakageMediumAudit checklist for every external surface
White-label support burdenMediumFeature-tiered white-label, self-serve docs, premium pricing
"Unlimited" marketing vs actual costsMediumInternal controls always enforce caps; marketing is separate concern



14. Acceptance Criteria


14.1 MVP Acceptance Criteria (Layer A + B)

1. An agency owner can sign up, add 5 clients, invite 2 team members, and run scans on all clients

2. A team member with "analyst" role can view clients and run scans but cannot change billing or manage team

3. Every API endpoint enforces RBAC server-side; role leakage is not possible

4. The agency overview dashboard shows all clients sorted by score with trend indicators

5. Citation checks run against minimum 2 AI models and show mention status

6. Fix engine shows prioritised fixes with generated assets, status tracking, and owner

7. Competitor comparison shows side-by-side scores with gap analysis

8. Usage is tracked per organisation and exposed in the billing/settings area

9. Entitlements are enforced via entitlements table, not scattered business logic

10. An agency can show before/after improvement clearly enough for a client to understand it in under 2 minutes


14.2 Phase 2 Acceptance Criteria (Layer C + D)

1. A user can generate a branded PDF report for any client and share it via link with configurable expiry and revoke

2. A user can view before/after score comparison between any two scans

3. An agency can generate a prospect audit and use it in a sales workflow

4. Scheduled weekly scans run automatically and send email notification on completion

5. API allows triggering a scan and retrieving results programmatically

6. Webhooks can be registered and delivered reliably

7. White-label branding works correctly on client-facing outputs without leaking SearchScore identity

8. One large agency cannot degrade platform performance for others (queue isolation verified)

9. API usage is correctly metered and visible in billing usage

10. Share links support expiry and revoke; reports never expose internal metadata

11. Estimated score gains on fixes are clearly labelled as estimates




15. Strategic Direction: Tool First, Platform Second


This is the most important strategic instruction for the build.


SearchScore must first succeed as:

• A high-value agency tool

• A client reporting and audit engine

• A retention and sales support system


Only then expand into:

• Infrastructure

• Programmatic access

• Deeper automation


Optimise the build for:

• Strongest agency UI

• Fastest time to value

• Best reporting experience

• Strongest fix workflow


NOT for:

• Maximum platform complexity on day one

• Generic dashboard bloat

• Feature completeness over commercial clarity


Non-negotiable guardrails:

• No accidental margin traps

• No fake unlimited plans

• No underpriced white-label

• No casual API giveaway

• No generic dashboard bloat

• No loss of category focus


The final product should feel like:

"The clearest, most commercially useful way for an agency to show why a client is not being recommended by AI, fix it, and prove the result."

Not:

• a generic SEO dashboard

• a broad marketing platform

• a raw analytics console

• a cheap white-label data utility




*End of specification.*