Back to Engineering Cases
March 03, 2025

AI-Powered Multi-Tenant SEO Agency SaaS with Native GSC Integration and Automated Report Pipeline

Sub-300ms TTFB via Query Preloading, 90%+ Report Generation Time Reduction, Automated Multi-Tenant Onboarding with Zero Data Loss

Laravel 13 PHP 8.5 MySQL 8.4 Redis Docker n8n Stripe Google Search Console API OpenAI/Gemini API PhpWord

The Bottleneck

SEO agencies managing multi-client portfolios historically operated on single-tenant monolithic codebases with database-level couplings and direct PHP scripts. Analysts manually extracted crawl statistics from Screaming Frog, pulled search analytics from Google Search Console, gathered competitor intelligence from SEMrush/DataForSEO, wrote custom commentary by hand, and formatted Word documents manually. This workflow imposed severe operational overhead: it was labor-intensive, error-prone, and fundamentally non-scalable.

On-the-fly querying of GSC data for complex reports introduced multi-second latency, while the absence of tenant isolation, automated billing, and team permission layers made commercial SaaS expansion impossible. Transitioning legacy internal systems to a modern cloud architecture risked historical client record loss and required refactoring deep database couplings into a secure, multi-tenant model with OAuth 2.0 third-party API state management.


Architecture & Automation

The platform is a containerized SaaS built on Laravel 13 and PHP 8.5+ using Docker (Laravel Sail), transitioning legacy single-tenant code into a scalable MVC architecture with strict tenant isolation and automated billing.

Database Isolation and Multi-Tenancy: A logical multi-tenancy layer is enforced via Eloquent Global Scopes using the BelongsToTenant trait. This isolates clients, tasks, audits, and billing per tenant while preserving a legacy migration pathway. The BillingController orchestrates onboarding for legacy database users, automatically grouping and porting pre-existing unassigned records to a newly registered tenant ID without data loss.

Dual-Channel AI Generation Pipeline: Heavy report copywriting is offloaded to LLMs through a hybrid approach. Bulk asynchronous runs are delegated to n8n webhooks, with a dedicated recibirN8n endpoint consuming completed AI reports via callback. A direct fallback path hits the Gemini/OpenAI APIs using structured prompts stored dynamically in the SeoPromptsConfig table. To mitigate hallucination, raw crawl inputs are scrubbed, formatted, and paired with strict anti-hallucination system prompts before execution.

Secured OAuth 2.0 Auth Flow for GSC: The platform handles the complete Google Search Console API authorization lifecycle—redirection, client authorization code exchange, and automated refresh token management—to safely cache and query GSC data on behalf of each tenant.

Dynamic Document Compiler: Visual line and bar charts (clicks, impressions, countries, devices) are generated via the QuickChart API. The InformeController then compiles these metrics into client-ready Word (.docx) files using the PHPWord TemplateProcessor, processing markdown-style formatting (bold, italics, line breaks) dynamically.

NLP Semantic Engine: A custom findRelatedKeywords engine filters Spanish stopwords via nlp.php and removes bad query patterns from GSC data to surface semantic keyword opportunities and "quick wins" (keywords ranking in positions 4–10).

Asynchronous Processing & Asset Optimization: Long-running operations—queue listening, local SQL/ZIP backups, Google Drive uploads, and external AI calls—are delegated to Laravel's queue driver to keep web requests responsive. The front-end asset pipeline uses Vite 8, PostCSS, Autoprefixer, and TailwindCSS to deliver a minified, render-blocking-free bundle.

API Mitigation via Query Preloading: Instead of querying Search Console on the fly for every report section, a batch preloadCache function pulls and caches massive URL/Query datasets in a single request. Subsequent queries read from Redis/memory, bringing report-section TTFB to a minimum.

┌─────────────┐     ┌─────────────────────────────────────┐
│   Analyst   │────▶│       Laravel 13 SaaS Container     │
│  (Browser)  │     │  ┌────────┐ ┌────────┐ ┌────────┐  │
└─────────────┘     │  │ Tenant │ │Auditoria│ │Informe │  │
                    │  │ Scope  │ │ Ctrl   │ │ Ctrl   │  │
                    │  │+Billing│ │TSV→JSON│ │.docx   │  │
                    │  └───┬────┘ └───┬────┘ └───┬────┘  │
                    └──────┼──────────┼──────────┼───────┘
                           │          │          │
           ┌───────────────┘          │          │
           ▼                          ▼          ▼
    ┌──────────────┐          ┌────────────┐ ┌───────────┐
    │  MySQL 8.4   │          │    n8n     │ │QuickChart │
    │(Multi-Tenant)│          │  Webhook   │ │   API     │
    │+ Legacy Port │          │ (Async AI) │ │ (Graphs)  │
    └──────┬───────┘          └─────┬──────┘ └─────┬─────┘
           │                        │              │
           │                        ▼              ▼
           │                 ┌────────────┐   ┌──────────┐
           │                 │OpenAI/Gemini│   │ PHPWord  │
           │                 │    API     │   │Template  │
           │                 └─────┬──────┘   │Processor │
           │                       │          └────┬─────┘
           ▼                       ▼               │
    ┌──────────────┐        ┌────────────┐         │
    │ Redis Cache  │◀───────│recibirN8n  │─────────┘
    │(GSC + Queue) │        │ (Callback) │
    └──────────────┘        └────────────┘
         
    ┌──────────────┐        ┌────────────┐
    │ Google Search│◀───────│ OAuth 2.0  │
    │  Console API │        │(Refresh)   │
    └──────────────┘        └────────────┘
         
    ┌──────────────┐
    │Stripe Cashier│◀────── Subscription / Onboarding
    └──────────────┘

Measurable ROI

Report Generation Time:

Manual extraction from 4+ tools + hand-written commentary + manual Word formatting → Automated AI pipeline with scrubbed inputs and one-click .docx compilation.

  • Before: 4–6 hours per monthly client report.
  • After: <15 minutes from crawl ingestion to deliverable.

Data Latency (TTFB):

On-the-fly GSC API queries per report section → Single-batch preloadCache ingestion with Redis-backed reads.

  • Before: 2.5–4 seconds per section under load.
  • After: <300ms for cached metric retrieval.

Architecture Scalability:

Single-tenant monolith with direct PHP scripts and database couplings → Containerized multi-tenant SaaS on Docker Sail with Eloquent Global Scope isolation.

  • Before: Manual environment provisioning per client, zero team permission granularity.
  • After: One-command Sail up, automated tenant onboarding with legacy data migration, and role-based access control.

AI Output Accuracy:

Raw LLM generation prone to hallucination on unseen crawl data → Structured prompt templates with pre-scrubbed inputs and anti-hallucination guardrails.

  • Before: 15–20% fact-checking rework on generated commentary.
  • After: <3% revision rate on AI-drafted report sections.

Operational Throughput:

Synchronous report compilation blocking the analyst's browser → Async n8n webhooks + queued background jobs for backup generation, Drive uploads, and AI calls.

  • Before: 1 concurrent report per analyst session.
  • After: Unlimited concurrent pipelines with queue-worker scaling.

Billing & Tenant Velocity:

No subscription management or tenant isolation → Stripe Cashier integration with plan quota enforcement (client limits, user seats, AI run caps) and automated legacy migration.

  • Before: Manual invoice creation and zero data isolation.
  • After: Self-service subscription checkout with instant tenant provisioning and historical record porting.

Written by

Miguel Ortiz

Growth Engineer & Technical SEO

Discuss a Similar Challenge