Market intelligence
What the competitor set says
Computed from the 11-product Kalodata export
Price positioning
Average realised unit price by segment, last 30 days
Price vs. units sold
Both axes logarithmic · bubble area = revenue · hover a bubble
Competitor comparison
Feature differentiation
From each listing's variation notes · only us marks features no competitor lists
Data checks on this import
- The export has no review-count column, only star rating. Add review counts to the next Kalodata pull so the table can rank by social proof.
- Our list price is entered as “32.95 (different on kalodata)”. Kalodata's realised average is $33.41, above list. Worth confirming which price is live.
- Commission rate shows “–” for Scalp Direct, while the margin sheet assumes a 20% creator commission. If no open-plan commission is set on the listing, that alone explains the low creator count.
- Findry and Tocoles list price ranges (variants); the table uses the low end for list price and Kalodata's average for positioning.
Inputs
Creator commission applies, no ad spend
Ads-sale fee replaces commission, plus ad spend
Price ladder
The sheet's price points, recalculated live with your inputs · click a row to load that price
Fixes needed in the margin sheet
- The sheet title says 11% commission, but the formula in F5 is =B5*20%. This calculator defaults to 20% to match the numbers; change it above if 11% is the real rate.
- The “Breakeven ROI on Ads (ROAS)” column divides price by net profit after ad spend (=B5/M5). Breakeven ROAS is price ÷ profit before ad spend. At $31.95 the true breakeven is 2.33, not 3.48; at $18 the sheet shows −7.11, which has no meaning.
- The chargeable-weight cell returns #DIV/0!. The tier itself is right (see the FBT check).
- Row 1 of the ads scenario uses $0 ad spend while every other row uses $4.55, so its ads margin (44%) isn't comparable with the rest of the column.
Sales GMV
Weekly
ROAS
GMV ÷ ad spend
Affiliate activity by week
Bars compare weeks within each row
Report log
Add a weekly report
Saved for everyone with access to this dashboard
Data checks on the progress sheet
- The “Samples approved” total in the header is 7, but the weekly rows add up to 8 (0 + 2 + 5 + 1). The total cell is typed in, not a formula.
- Week of 21 Sep records showcase additions as text (“5 for Serums – 234 for Hair Oil Applicator”). This log stores 234 for the applicator and keeps the serum count in notes, so the column stays numeric.
- Week ranges are uneven (Mon–Sat, Mon–Sun, Mon–Fri, Sat–Fri). Fixing a Monday–Sunday week makes week-over-week changes comparable.
- Every week here records 0 auto-approved samples, but the sample requests sheet shows 2 (fruitandsunlight, hamsitha_reddy). See Creator samples.
- The sheet has no sales GMV, ad spend or units. Those fields are ready in the form; the GMV and ROAS charts fill in as soon as the first week is logged.
Sample funnel
Each creator counted at the furthest stage reached
Needs follow-up
Approved creators with no content yet
Creators
Update creator
Saved for everyone with access
Data checks on the sample sheets
- The requests sheet spells one creator hawnilovesit; the approved sheet has shawnilovesit. They're merged here as one creator. Confirm which handle is right.
- Two creators are auto-approved in the requests sheet (fruitandsunlight, hamsitha_reddy) but missing from the approved sheet, so their shipping and content aren't tracked. The weekly log also records 0 auto-approved.
- The requests sheet has 28 rows for 26 creators: iam_evveiiii is listed twice, and nayanatural asked for a refundable sample before getting a free one. The weekly log totals 25 requests and 8 approvals, so the two sources don't agree yet.
- No request dates are recorded, so time-to-approve can't be measured. The approved sheet mixes typed dates (25-09-2026) with real dates, and GMV / items fields mix numbers, “1.7k” text and ranges (“0-5k$”, “100-1k”).
- nayanatural has two videos in one cell but only the first is a working link; views are typed as “293 & 794” (stored here as 1,087). The Email/WhatsApp column is empty for all 8 creators.
TikTok return reason
What the buyer selected
What buyers actually say
Tagged from buyer notes · a case can carry more than one
What the returns point to
Computed from the return log
Return log
Newest orders first (TikTok order IDs increase over time).
Data checks on the returns export
- The export has no request date and no refund amount, so a return rate per period and the refund cost can't be calculated. Add “Return request time” and “Refund amount” to the next export.
- Two tracking IDs (792192585588, 792191534271) were stored by Excel as numbers. Format that column as text so longer IDs aren't rounded.
- Six cases sit under the older listing title (“Direct-to-Scalp … Stimulator Brush”). It's the same product, so they're counted together.
- Three “refunds” are refundable-sample payouts to creators (dailylaughsss, theequeenofheart, anila.wali), not customer returns. None of the three appear in the sample requests sheet.
- The sheet's own summary (38 cases, 15 “No longer needed”, 8 defective …) matches the rows.
Layout wireframe
Same shell for every module
Below 860px the sidebar turns into a scrolling tab strip and panels stack to one column.
Data flow
flowchart LR K[Kalodata export .xlsx] --> I[Import API
parse + validate] M[Margin inputs] --> I W[Weekly form / CSV] --> I T[TikTok Shop Open API
phase 2] -.-> I I --> DB[(Postgres
row-level security)] DB --> V[Dashboard
Next.js on Vercel] A[Auth + roles] --> DB A --> V
Recommended stack
Launch path: this prototype → Next.js + Supabase in about two weeks
| Option | Speed to launch | Custom calculator & charts | Per-brand data isolation | Best fit |
|---|---|---|---|---|
| Next.js + Supabase + Tailwind on Vercel (recommended) | 1–2 weeks | Full control; these modules port directly to React components | Postgres row-level security per brand | A client-facing product you'll extend to every brand THE WE ONE manages |
| Retool + Supabase | Days | Good tables and forms; charts are stock | Strong (Retool groups + RLS underneath) | Internal ops console for brand managers; per-seat cost grows with client logins |
| Softr on Airtable / Supabase | Days | Limited; calculators need workarounds | Record-level user groups | Simple client portal that mostly shows read-only reports |
| Glide | Days | Limited; mobile-first layouts | Row owners | A phone app for logging creator outreach on the go |
Security model
- Sign-in: Supabase Auth with Google Workspace SSO for the agency domain and magic-link for client users. MFA required for Owner and Admin.
- Role-based access: roles live in a memberships table (user × brand × role), so one person can be a Brand Manager on Scalp Direct and have no access to other clients.
- Enforced in the database: every table carries brand_id and has row-level security policies. A bug in the UI can't leak another brand's data.
- Cost data is narrower: COGS and margin scenarios are hidden from the research role; clients see their own margins only.
- Secrets stay server-side: the Supabase service key and any TikTok Shop API tokens live in Vercel environment variables and run only in server routes.
- Uploads: spreadsheets are parsed server-side, validated against a schema, and the original file is kept in a private storage bucket reachable only by signed URL.
- Audit trail: a trigger writes who changed what (with a JSON diff) for weekly reports and margin scenarios.
- Backups & previews: point-in-time recovery on the database; Vercel preview deployments behind password protection.
Role permissions
| Role | Market | Margins | Weekly | Settings |
|---|---|---|---|---|
| Agency owner | Edit | Edit | Edit | Edit |
| Agency admin (COO / CGO) | Edit | Edit | Edit | View |
| Brand manager | View | Edit | Edit | — |
| Research analyst | Edit | — | View | — |
| Client viewer | View | View | View | — |