HAP
All work02 / 09

Dashboards & Reporting

Multi-Client Amazon Ads Command Center

An internal agency tool for managing several Amazon advertising clients from one app. Each brand gets its own dashboard that authenticates to Amazon, pulls campaign and search-term performance, version-controls the account's bulksheet, and runs an AI strategist that turns raw spend data into prioritized actions. It was built to replace hours of manual spreadsheet wrangling with a single place to see what changed and what to do next.

Stack

Next.js 16React 19TypeScriptAmazon SP-API + Ads APIaws4 (SigV4)xlsx (SheetJS)Tailwind CSS 4

Concepts

Multi-tenantOAuth token pipelineBulksheet diffingAsync report pollingAI analysis agent

How it works

The whole flow, traced from your first tap.

Browser · React 19Next.js APILocal data storeAmazon APIs + AI agent
  1. 01

    Browser · React 19

    Pick a client and pull live data

    Each client gets its own route, settings page and API namespace, so the whole dashboard re-skins itself per brand while reusing one engine keyed on the brand name.

    Next.js App RouterPer-brand routesfetch
  2. 02

    Next.js API

    Authenticate to Amazon under the hood

    Hitting refresh swaps a stored refresh token for a short-lived access token via Login-with-Amazon, and for SP-API it signs every request with AWS SigV4 in spSigner.ts so two completely different Amazon auth schemes are handled transparently.

    LwA OAuthAWS SigV4aws4
  3. 03

    Amazon Ads API

    Fetch campaign and search-term reports

    The app requests async reports with Amazon's versioned content-types, polls each report id until it reports COMPLETED, then downloads the gzipped JSON and unzips it server-side, with a freshness window so it reuses a recent snapshot instead of re-hitting Amazon every time.

    Async report jobsStatus pollinggunzip
  4. 04

    Next.js API · SheetJS

    Upload the weekly bulksheet and see what changed

    Dropping the .xlsx parses every sheet into eleven normalized entity tables in bulksheet-parser.ts, then diffs it against the last snapshot field-by-field, so a single bid going from 0.75 to 0.82 surfaces as one labeled change tied to its campaign and ad group instead of a wall of rows.

    xlsxEntity diffJSON snapshot store
  5. 05

    AI agent

    Ask plain-English questions about the account

    The ask endpoint serializes the current account state and recent change log into a prompt and shells out to the Claude CLI, so a user can ask things like did my pause take effect and get an answer grounded in the actual diff history.

    Claude CLIchild_processState + delta context
  6. 06

    AI agent

    Run the AI strategist across multiple windows

    One click fans out weekly, bi-weekly and monthly analyses in parallel with Promise.allSettled, each producing structured JSON of negatives, problem campaigns and winners, then a synthesis pass finds the patterns confirmed across periods while the UI polls server-side progress to light up each agent as it finishes.

    Parallel analysisPromise.allSettledPoll-based progress

The problem

Running Amazon ads for multiple clients means juggling separate logins, two different Amazon APIs with their own auth schemes, and giant bulksheet exports where a single bid change is buried among thousands of rows. There was no fast way to answer basic questions like did last week's change actually take effect, or which search terms are wasting money, without manually combing through Excel for every account.

What we built

A brand-segmented Next.js app where each client has its own route, settings, data store, and API namespace. Every brand dashboard can authenticate to Amazon, fetch live campaign and search-term reports, ingest the weekly bulksheet, show a structured diff of what changed since the last upload, and generate an AI performance analysis. The same engine is reused per brand by keying state files and folders on the brand name.

Two Amazon APIs, two auth schemes, one pipeline

The Ads API runs on Login-with-Amazon OAuth (refresh-token exchange in lwa.ts) while SP-API additionally requires AWS SigV4 request signing, handled in spSigner.ts with the aws4 library. The Ads reporting flow in adsApi.ts speaks the quirky versioned content-types the API demands, kicks off async report jobs, polls them to COMPLETED, then downloads and gunzips the GZIP_JSON payload before normalizing it into clean rows.

Outcome

One operator can run several Amazon ad accounts from a single screen: refresh live data, see exactly what changed in the latest bulksheet down to the individual bid, ask plain-English questions about the account, and get a prioritized list of negatives and budget moves. Snapshots and bulksheet archives are persisted per brand, so every upload builds a running history instead of a one-off look.

Interested in something similar?

Tell us what you need and we'll figure out how to ship it.

Get in touch