1. Executive Summary
FixAdSpend is a SaaS platform that helps small businesses and digital agencies audit and optimize their Google Ads spend using AI-powered analysis. The product reads campaign, ad group, ad, and keyword performance data from Google Ads via the official Google Ads API and surfaces optimization recommendations in a customer dashboard. All actions that mutate the customer's account (pausing campaigns, adjusting bids, adding negative keywords) require explicit approval through the FixAdSpend UI unless the customer has opted into the optional Autonomous Agent mode, which applies a defined whitelist of low-risk changes with a full audit trail.
The application is built on Next.js 14 hosted on Vercel, with PostgreSQL (Neon) for primary storage, Prisma as the ORM, and Anthropic Claude as the AI inference layer. Customer OAuth tokens are encrypted with AES-256-GCM at rest using a key stored in Vercel environment variables. The product is live at https://fixadspend.ai and the Google Cloud OAuth client and Developer Token are already configured under the Fixadspend LLC Manager Account (MCC 482-246-6852).
2. Product Overview
2.1 Target customer
Small to mid-market e-commerce brands, in-house marketing teams, and digital advertising agencies typically spending US$1,000 to US$500,000 per month on Google Ads and Meta Ads combined. Agencies manage multiple client accounts via the standard MCC structure.
2.2 Value delivered
- A read-only audit report in under 5 minutes identifying wasted ad spend
- Plain-English recommendations: which campaigns to pause, which bids to adjust, which negative keywords to add, with estimated savings per recommendation
- An optional Autonomous Agent that can apply a defined whitelist of low-risk changes on a schedule, with full audit trail and one-click undo
- True profit per campaign (when Shopify is connected) instead of vanity ROAS
2.3 Pricing
FREE tier (read-only audit only). Paid tiers from $29/month to $2,499/month, differentiated by number of brands managed, monthly decision quota, and feature gates. Billing handled by Stripe.
3. System Architecture
FixAdSpend is a three-tier web application:
- Frontend: Next.js 14 React application served by Vercel. Tailwind CSS, lucide-react icons. Runs at
https://fixadspend.ai. - Backend: Next.js API routes (Node.js runtime) served by the same Vercel deployment. Stateless request handlers. Background work runs via Vercel Cron triggers hitting internal
/api/cron/*endpoints on a schedule. - Database: PostgreSQL hosted on Neon. Prisma ORM. Schema includes
User,Organization,AdAccount,Campaign,CampaignSnapshot,AIDecision, and audit-log tables. - AI inference: Claude (Anthropic) via the Messages API and Batch API. Anthropic is contractually a data processor; we do not use third-party models that train on customer data.
- Authentication: NextAuth with email + password and Google OAuth (for sign-in only, not for Google Ads). Sessions are JWT-backed.
- Encryption: All OAuth refresh tokens for connected platforms (Google Ads, Meta, Shopify) are encrypted with AES-256-GCM before storage using
TOKEN_ENCRYPTION_KEY. The key is stored in Vercel environment variables and never logged.
4. Google Ads API Usage
4.1 OAuth scopes requested
Exactly one OAuth scope is requested: https://www.googleapis.com/auth/adwords. No additional Google API scopes are requested for Ads functionality. (NextAuth Google sign-in uses the standard openid email profile scopes which are separate from Ads API access.)
4.2 Resources read (GoogleAdsService.SearchStream)
We issue GAQL queries to read the following resources for the customer's authorized accounts:
customer— id, currency_code, time_zone, descriptive_name, manager flag, login_customer_id linkagecustomer_client— to enumerate child accounts under an MCCcampaign— id, name, status, advertising_channel_type (SEARCH, SHOPPING, PERFORMANCE_MAX, DISPLAY, VIDEO), bidding_strategy_type, campaign_budgetad_group— id, name, status, type, cpc_bid_microsad_group_ad— id, ad.type, ad.responsive_search_ad headlines/descriptions (for creative-fatigue analysis), statuskeyword_view— keyword.text, keyword.match_typesearch_term_view— search_term, ad_group, conversions (for negative-keyword recommendations)campaign_budget— amount_micros, delivery_methodmetricson all of the above — impressions, clicks, conversions, conversions_value, cost_micros, average_cpc, ctr, cost_per_conversion, search_impression_share
Default lookback window is the last 30 days. Configurable to 90 days. Sync runs hourly via Vercel Cron.
4.3 Resources mutated (GoogleAdsService.Mutate)
Mutate operations are only performed when (a) the customer has approved a specific recommendation in the UI, or (b) the customer has opted into Autonomous Agent mode AND the proposed mutation matches the agent's whitelist. The mutations the product can perform are limited to:
campaign.status— PAUSED / ENABLED togglesad_group_criterion— adding negative keywords at ad-group or campaign levelcampaign_budget.amount_micros— increasing/decreasing budget within ±50% per changead_group_criterion.cpc_bid_micros— bid adjustments within ±30% per change
The product cannot and does not: create new campaigns, modify ad copy, change billing settings, link/unlink Google Ads accounts, modify conversion settings, or move money outside the customer's existing campaigns.
4.4 Estimated quota usage
- Operations per customer per day: ~50–200 reads + 0–10 mutates
- Initial customer cohort (first 90 days): ≤500 customers
- Estimated peak daily operations: 10,000 – 50,000
- Backoff strategy: exponential backoff on RESOURCE_EXHAUSTED, retry-with-jitter on transient errors, queueing for any 429 responses
5. Data Flow
5.1 Inbound (Google Ads API → our system)
- Vercel Cron triggers
/api/cron/synchourly - For each active customer, we decrypt the stored Google Ads refresh token
- We exchange it for a short-lived access token via Google's token endpoint
- We issue parallel GAQL queries against the resources listed in §4.2
- Results are normalized into our schema (one row per campaign per day) and written to PostgreSQL as
CampaignSnapshotrows - The access token is discarded; the refresh token remains encrypted in our database
5.2 AI processing
After each sync, the relevant snapshot rows are passed to our analysis engines. Each engine prepares a structured prompt (in JSON) containing campaign-level metrics — never raw user PII — and submits it to Anthropic's Claude API. Claude returns a structured JSON analysis which we parse, validate, and write to the AIDecision table for display in the customer dashboard. We use prompt caching to minimize repeated token costs and the Anthropic Batch API for non-realtime nightly analyses.
Anthropic operates as a data processor under contract; they do not train foundation models on data we send. We do not share Google Ads data with any other third party for any purpose.
5.3 Outbound (mutations back to Google Ads)
- Customer approves a recommendation in the dashboard (or Autonomous Agent picks one from the whitelist)
- Backend handler validates the operation type is in the allowed mutation set (§4.3)
- Decrypts the customer's Google Ads refresh token, exchanges for an access token
- Calls
GoogleAdsService.Mutatewith the partial-resource update - Writes the result + Google's response to our audit log (
AgentDecisionOutcometable) for traceability - Shows the customer the result with a one-click undo for 24 hours
6. Data Storage and Retention
- Primary storage: PostgreSQL on Neon (US East region). Encrypted at rest by the platform; encrypted in transit via TLS 1.3.
- Refresh tokens: AES-256-GCM encrypted with an application-layer key before write. The encryption key is held only in Vercel environment variables.
- Access tokens: never persisted. Exchanged from refresh token on demand and discarded after the request.
- Active retention: Google Ads data is retained while the connection is active and for the duration of the customer's subscription.
- Disconnection: When a customer disconnects Google Ads from the Integrations page, we stop syncing immediately and delete the refresh token. Historical snapshots are retained for 30 days for audit history; after 30 days they are purged.
- Account deletion: When a customer deletes their FixAdSpend account or requests deletion via /data-deletion, we purge their account record, all CampaignSnapshot rows, AIDecision rows, and OAuth tokens within 30 days. Backups age out and overwrite within the same 30 days.
- No data brokers: Google Ads data is never sold, transferred to data brokers, or used for advertising unrelated to the customer's own account.
7. Security Model
- HTTPS-only across all customer-facing endpoints (Vercel enforces TLS).
- Database connection uses TLS 1.3 with Neon's managed certificates.
- OAuth refresh tokens encrypted with AES-256-GCM application-layer encryption (§6).
- Web sessions are JWT, signed with NextAuth's session secret. Short-lived (30 days) with rotation.
- API routes that perform mutations require authenticated session + CSRF token + per-request ownership check (the operation must be on a Google Ads account currently linked to the requesting user's organization).
- Rate limits on every customer-facing endpoint to prevent abuse (per-user burst cap of 30 requests/minute).
- Per-user monthly LLM spend caps to prevent runaway costs from a compromised account.
- All admin actions are logged to an immutable audit log.
- Vercel and Neon are SOC 2 Type II certified.
8. OAuth Authorization Sequence
- Customer signs in to FixAdSpend and clicks “Connect Google Ads” in the Integrations page
- Browser is redirected to
https://accounts.google.com/o/oauth2/v2/authwith our OAuth Client ID, thehttps://www.googleapis.com/auth/adwordsscope,access_type=offline,prompt=consent, and a CSRF state parameter - Customer reviews Google's standard consent screen and grants access
- Google redirects to
https://fixadspend.ai/api/integrations/google/callbackwith an authorization code - Our callback handler validates the CSRF state, exchanges the code for a refresh token + access token at Google's token endpoint
- The refresh token is encrypted and persisted; the access token is used for the first sync then discarded
- Customer is redirected back to their dashboard which begins populating within 5 minutes
No password, credential, or session belonging to the customer's Google account is ever transmitted to or stored by FixAdSpend. Authentication happens entirely between the customer and Google.
9. User Experience
The product is fully self-serve. Reviewers can verify the design described in this document by:
- Visiting https://fixadspend.ai/register and creating an account
- Clicking “Connect Google Ads” on the dashboard onboarding hero — this triggers the OAuth flow described in §8
- Reviewing the dashboard once data populates (~5 minutes after consent)
- Viewing the recommendations list and the per-recommendation approval interface
Pre-seeded demo credentials and a 3-minute video walkthrough are available within one business day on request to admin@fixadspend.ai.
10. Compliance Attestations
- Use of data received from Google APIs complies with the Google API Services User Data Policy, including the Limited Use requirements
- We use the data only to provide the user-facing optimization features described in this document
- We do not sell or transfer Google Ads data, except as needed to provide or improve user-facing features, to comply with applicable law, or as part of a merger or acquisition where the acquirer agrees to be bound by these obligations
- We do not use Google Ads data to serve advertisements
- We do not allow humans to read the data except (a) with the user's affirmative agreement for specific support requests, (b) for security investigations, or (c) to comply with applicable law
- Privacy disclosures are at /privacy (Section 7: Google User Data — Limited Use)
- Data deletion workflow is documented at /data-deletion
11. Company & Contact
- Legal entity: Fixadspend LLC
- Jurisdiction: Wyoming, United States
- Address: 30 N Gould St Ste R, Sheridan, WY 82801, USA
- API contact email: admin@fixadspend.ai
- Phone: +1 (307) 445-5353
- Website: https://fixadspend.ai
- MCC ID:
482-246-6852
This document is a living description of the FixAdSpend tool design. Substantive changes to API usage, mutations, or data handling will be reflected in updated versions of this page. Current version: 1.0 — June 25, 2026.