auto-pulled per source from platform APIs · refreshed hourly
Total Spend
$0
all platforms
Qualified Calls
—
5 closer teams · Auto-QA verified
Closing %
—
deals / qualified calls
CPQC
—
spend / qualified calls
CPA
—
spend / deals
ROAS
—
revenue / spend
Budget Pacing
business-day pacing · saved for everyone
Sources
Source
Spend
Deals
Avg Tax Debt
PIF
PS
PN
Revenue
CPA
ROAS
Rangeor pick:→
Revenue per Agent
Loading…
Company revenue (ADServe excluded, net of refunds — same figure as the hero card) credited to each settlement officer / closer for the selected window.
Deals per Agent
Loading…
Investigations and resolutions sold (deal count only) credited to each
settlement officer / closer for the selected window. ADServe excluded, same
live deal feed as the hero cards. For dollars, see Revenue per Agent.
Investigations
Resolutions
Staffing & Capacity — Hire · Hold · Cut
Per-Deal Economics — Cost vs Lifetime Return
scale by ROI, not CPA
The whole question in three numbers, per deal: ① what it COST to acquire, ② what it's EARNED so far, ③ what it'll earn over its LIFETIME → the Lifetime ROI. If the ROI is strong, the CPA doesn't matter — we keep buying. (Recent months' ② and ③ are still maturing — see the % under each month.)
Revenue Month
Dealstotal TIs
① Cost / DealCPA · what we paid
② Revenue Collected / Dealso far · climbing
③ Lifetime Value / Dealprojected total
Lifetime ROI③ ÷ ① · the verdict
Live Traffic
Loading…
Google Analytics realtime for freshstartrelief.com, mirrored here so you don't have to open analytics.google.com.
Refreshes itself every minute. GA4's realtime API exposes page titles, not paths, so variants read as
"Landing Page TikTok Custom Form – V6".
Active users in last 30 minutes
—
Views in last 30 minutes
—
Active users per minute
Page title · last 30 minutes
Company Accolades
Loading…
Every record shows the mark it beat, so "record" means something you can check.
Money figures are company revenue with ADServe excluded, matching the rest of the board.
Records marked from tracker come from the manually kept Company Accolades sheet and
cover dates earlier than our tables reach.
Personal bests set this month
ROI by Source
Loading…
For every $1 spent on ads, how much cash comes back over the life of the customer?
Counted per source, on the deals sold in the chosen months, using every payment those customers have made so far (projected to 14 months).
Target: $2 back per $1.
Details by month (for analysts)
Cash per deal at equal age, and cost per deal, by month sold
Other sources by month
How this is calculated
Pace to Beat Last Month
Company floor revenue, net of refunds, ADServe excluded
—
—
projected end of month
Month-by-Month: Where Each Month's Revenue Came From
Each row = the TIs we generated that month, tracked by Case ID. What they COST (Ad Spend → CPA per deal) vs what we EXTRACTED from them (LTV = every dollar those deals ever pay, ADServe excluded, net of refunds) → the RETURN (Cohort ROAS = LTV ÷ Spend). The middle columns just break that down. The blue/green split = revenue collected THIS month: blue from deals sold this month, green recurring from prior months — sums to Total Revenue (Without ADServe), company-only.
LIFETIME = tracks the cohort over time — recent months understate (still maturing)THIS MONTH = locked to that calendar month~% mature (under each month) = how much of that cohort's lifetime revenue has landed; LIFETIME columns climb until ~9 monthsSame-Month revenueRecurring revenue
Total Revenue (Without ADServe)THIS MONTH · CASH IN
Total Revenue (With ADServe)THIS MONTH · CASH IN
From Same-Month Deals
Recurring From Previous Months
Cohort ROAS LTV ÷ SpendLIFETIME · THE ANSWER
Contracted signed feesLIFETIME · CEILING
% CollectedLIFETIME
Projected Contracted × RLIFETIME · PROJECTED
Projected ROASLIFETIME · FORWARD
ROI With ADServeTHIS MONTH · CASH
ROI Without ADServeTHIS MONTH · CASH
Scale Score spend more?
Investigations
Resolutions
Same-Mo Total
Recurring Inv
Recurring Reso
Recurring Total
v6.6.0
v6.6.0 — REDDIT IS ITS OWN SOURCE (CMO 2026-09-08: "need the reddits on the sources"). Logics created four Reddit sources — 97 "Clear Start Tax Reddit Form", 98 "IRS Fresh Start Reddit Form", 99 "Clear Start Tax Reddit", 100 "IRS Fresh Start Reddit" — and the board handled NONE of them: the word "reddit" appeared zero times in this file. Every FSI Reddit deal would have fallen through the whole normalizeSource chain unchanged, missed CANONICAL_CAMPAIGNS, and landed in "Other (non-paid)" with the call and form labels sitting on two separate spend-less rows; isPaidDealSource returned false so they would also have been counted as organic in the hero card's paid/organic split; and platformForSpendSource sent any future Reddit spend to "Unallocated". Fixed the way Bing and StackAdapt were: "IRS Fresh Start Reddit" is now a SPEND_SOURCE (so a canonical row) and is PINNED into the Sources table — with 0 deals and $0 spend the row would otherwise not render at all, which is the precise invisibility the pin list was added for on 2026-06-11; drop the pin once Reddit has steady data — "IRS Fresh Start Reddit Form" folds to it via FORM_TO_PARENT — deliberately NOT LEGACY_COLLAPSE, which runs in every view mode and would have destroyed the call/form split exactly as it nearly did for StackAdapt in v6.5.1 — normalizeSource gains a /reddit/i branch, isPaidDealSource counts it paid, and Reddit joins SPEND_PLATFORM_ORDER. Position of the new branch is not load-bearing (nothing else matches "reddit" and "reddit" matches nothing else), which is the opposite of the stackadapt/native ordering trap. THE CST PAIR IS DELIBERATELY LEFT ORGANIC: the Reddit ad account (jjrvo13jjgjo) sits under the FSI business and there is no CST Reddit campaign, so "Clear Start Tax Reddit" keeps routing to "Clear Start Tax (organic)" alongside CST's other community surfaces (Quora, YouTube, LinkedIn, Medium, Pinterest). One line in the CST guard flips it if a paid CST Reddit campaign ever launches. Verified before shipping by running the EDITED normalizeSource/isPaidDealSource over all four CRM labels in both view modes. State at wiring: 0 Reddit deals in MySQL deals, 0 Reddit spend keys in ad_spend m_2026_07/08/09, 0 Reddit revenue docs — the sources were created ahead of launch. ⚠ Spend is NOT auto-pulled: GSM holds no Reddit OAuth app, so the row shows deals against $0 until the Ads API v3 developer app exists; add the sync-daily-spend pull and autofill platMap entry together at that point. lifetime-roi-precompute's bucket() gained the same branch so the ROI by Source page splits Reddit out instead of dropping it into Other. · v6.5.1 — StackAdapt keeps its call/form split. "IRS Fresh Start Native - Form" was in LEGACY_COLLAPSE, which runs in EVERY view mode, so the form label folded into the parent even on "Sources Individually" and StackAdapt would have been the one paid channel with no call/form split. Moved to FORM_TO_PARENT only (campaign/trends), matching "IRS Fresh Start Yahoo Form". Found by running the DEPLOYED normalizeSource over every label the CRM can now write, after n8n created "IRS Fresh Start Bing Form" (SourceID 102) at 10:37 AM: that same test proved Bing Form and Chatgpt Form already fold correctly in campaign mode and split correctly in individual mode via the 2026-07-17 durable fallback, so neither needed a change. · v6.5.0 — STACKADAPT IS ITS OWN SOURCE; BING SEPARATED FROM GOOGLE (CMO 2026-09-04: "need stack adapt here now · We have bing now too"). StackAdapt native went live 2026-09-03 (campaign group 406207, account 38208). Until today its CRM sources — "IRS Fresh Start Native" and "IRS Fresh Start Native - Form" — COLLAPSED INTO the Yahoo/Taboola bucket, which was right while Taboola was the only native vendor and wrong the moment a second one launched: StackAdapt deals were credited to Taboola and both rows' CPA was wrong. Native now maps to its own "IRS Fresh Start StackAdapt" row (the 2 legacy 2025 "Native" deals move with the label); advertorial "Articles" stay with Taboola, which is what they are. The normalizeSource chain tests stackadapt/native BEFORE the yahoo|taboola|article line, because that line still matches the word "native". Spend now flows: sync-daily-spend pulls campaignDelivery per day and autofill rolls it into m_YYYY_MM ($403.54 on 2026-09-03, 451,402 impressions, 245 clicks). 🔴 THE STACKADAPT TRAP, verified before wiring: a SINGLE-DAY window returns $0.00 — from=2026-09-03&to=2026-09-03 gives $0.00/0 impressions while from=2026-08-01&to=2026-09-04 gives the full $403.54 all bucketed on 09-03. A per-day loop, the obvious way to build daily docs, would have written a silent zero for every StackAdapt day. The sync queries a RANGE and reads records.nodes[].granularity.time, refuses a from==to window outright, and asserts the day sum foots to the API total before writing. (Two more shape notes: the granularity enum is DAILY not DAY, and the time-series dataType is GRAPH not CHART — TABLE+DAILY returns one row per CAMPAIGN with no date, which looks like daily data and is not.) Bing was already a first-class row here but lifetime-roi was folding its spend into Google; it now stands alone ($759 / 2 deals). ⚠ Bing spend is NOT auto-pulled: GSM holds MICROSOFT_ACCOUNT_ID / ACCOUNT_NUMBER / CUSTOMER_ID / DEVELOPER_TOKEN but no OAuth client id, secret or refresh token, which the Microsoft Ads API requires. · v6.4.3 — ROI by Source: the headline box is hidden until it has text (an empty green bar showed while the document loaded). · v6.4.2 — ROI by Source: the window aggregate now counts only months that carried both spend and deals toward cost per deal and "back per $1" (the precompute's own rule). Months with deals but no recorded spend, a source's organic/legacy months, were inflating the ratio: Clear Start Tax Meta read $471 per deal and $3.60 back on 43 deals when its only paid month is August ($2,027 per deal, $1.39 back); Taboola's spend-less April did the same in a smaller way. Seen on the first capture of v6.4.1. · v6.4.1 — ROI by Source polish, from the first capture of v6.4.0: the window filter now reads "Deals sold in · This year / Last 6 months / Last 3 months · or from … to …" (was "Cohorts · YTD / Last 6 / Last 3 · Range"), and the table's Trend column is compact ("▲ Improving $1.33 → $1.55") with the month spans in the tooltip so the last column no longer scrolls off screen. · v6.4.0 — ROI by Source, EXECUTIVE LAYOUT (CMO: "make it simpler so my executives understand it right away"). The page now leads with one question — for every $1 spent on ads, how much cash comes back over the customer's life? — answered in one headline sentence computed from the data, then big-number cards ("$1 → $1.37") for the company and the biggest sources with a plain verdict (Strong $2+, Good $1.50–2, Thin $1–1.50, Losing under $1) and an arrow that says Improving / Worsening / Flat, the cost per deal, the cost per deal that would give $2 back, and this month's cost per deal as a green/orange pill against that number. The table below uses the same plain words (Ad spend · Deals · Cost per deal · Cash per deal over life · Back per $1 · Trend · Cost per deal for $2 back · This month's cost per deal). The window filter now reads "Deals sold in: This year / Last 6 months / Last 3 months / or From–To". Everything analytical (cash per deal at equal age by month, other sources by month, best/worst cohort, board ROAS vs flat spend, curve provenance, methodology notes) moved under two collapsed sections: "Details by month (for analysts)" and "How this is calculated". Nav label shortened to "ROI by Source". · v6.3.0 — Lifetime ROI page: DIRECTION + COHORT WINDOW (CMO, same afternoon: "where is it going up or down? … a time filter like the dashboard"). Direction column per source = lifetime cash ÷ spend of the most recent cohorts in the window that have at least one month of collections, against the cohorts before them (▲ improving / ▼ worsening / → within ±0.05x, with both values and the month spans printed); a cohort with no +1-month read is listed but never used for direction, because its lifetime estimate rests on ~34% of its cash. Second indicator: the running month's CPA against the last complete cohort's CPA (CPA is the leading indicator; up is coloured bad). Cohort-window filter above the table: YTD / Last 6 / Last 3 / From–To over cohort months; every column, the best/worst cohort, the trajectory tables and the per-source detail recompute from the window client-side (the nightly doc carries every cohort). First read, YTD: Google 1.29x → 1.53x ▲ (Feb–Apr → May–Jul) while Sep MTD CPA runs +35% over August. · v6.2.1 — Lifetime ROI page hotfix: the "computed at" stamp called fmtDay/fmtT, which are scoped inside the freshness-strip function, so renderRoi threw "fmtDay is not defined" after the Firestore read and the page sat on "Loading…" (caught on the live page 8 minutes after v6.2.0 shipped, via the console warning). Formats the timestamp locally. · v6.2.0 — LIFETIME ROI BY SOURCE (new left-nav page). The CMO asked whether ROI would "catch up to 2x" if spend were held flat. The board's monthly ROAS divides this month's cash by this month's spend, so growing spend depresses it (Aug 2026 Google: 1.26x on the board, 1.80x over the year's average spend); but under FLAT spend it converges to each source's LIFETIME CASH ÷ SPEND, which is what this page shows. Per source and per cohort (TIs sold that month, MySQL deals bucketed like the Sources table; spend keys folded the same way, incl. the spring's "Google - 2"/"Google Form"/"2HVT" keys): cash = every SOComm payment those cases have made to date, any team; lifetime = a 14-month estimate from the source's own two most recent mature cohorts (cash so far ÷ the share they had collected at the same age; company curve where a source lacks mature cohorts); M = lifetime cash ÷ spend; CPA for 2x = lifetime cash per deal ÷ 2. Trajectory tables show cash per deal at EQUAL AGE (sale month, +1, +3) beside CPA, so "are we heading the right way" is answerable cohort by cohort. Fed by ad-intel/scripts/adperf/lifetime-roi-precompute.mjs → lifetime_roi/current, nightly. First read (Jan–Aug 2026 cohorts): Google 1.37x at CPA $1,876 (2x needs ≤ $1,284), HVT 1.62x, Meta 1.65x, TikTok 1.59x, Taboola 2.32x, company 1.51x. Cash is not margin; Unallocated spend keys ($287k, Jan–Apr) are listed but assigned to no source. · v6.1.1 — CASH MOVES ON WEEKENDS. The revenue card withheld its month-over-month percentage whenever the benchmark window had no selling days, the same rule the deals and calls cards use. The CMO read the dash as "still blank, still not comparing to anything" and he was right: Aug 1-2 2026 was Sat/Sun with 0 calls and 1 deal, but it booked $40,808.33 in-house and $58,855.28 across all teams (his Logics Set. Officer Commission report, Team = All, for the same two days). A weekend is a real base for money. Revenue now always compares (Sep 1-2 $190,051 vs Aug 1-2 $40,808 = ▲366% in-house), and the context line prints BOTH bases so the card reconciles against Logics either way: in-house (what the hero shows) and all teams incl. ADServe ($58,855 = $40,808 + $18,047). Deals and calls keep the withheld % (a % against a weekend's 0-1 deals is noise) with the wording "benchmark days were Sat/Sun". · v6.1.0 — FULL-BOARD ACCURACY AUDIT (CMO: "each aspect, each feature, fan out"). Six read-only departments recomputed every figure from its source with commands and raw output; the board reproduced its own formulas to the dollar everywhere, and five things were genuinely wrong. FIXED IN THIS VERSION: (1) Year-over-year and older-month DEALS were deflated by the ADServe rule: "exclude any case that ever received ADServe cash" retro-erased year-old company TIs ("vs last yr 1-2" read 37, truth 41; every 2025 month's deals and CPA quietly low). A sale is now ADServe's only when ADServe cash lands around the sale itself (7 days before to 45 after). (2) Spend, calls and every precompute were ONE-SHOT reads at login while revenue and deals streamed live, so an open tab showed the 2:16 PM spend and 3:19 PM calls at 4:27 PM. The one-shot sets now re-read every 15 minutes while the tab is visible and when a hidden tab returns. (3) Labor Day (Sep 7) was a full selling day in the forecast (+$106,907 revenue, +49 deals), the biz-day pace, "1 of 22 biz days" and Budget "days left"; a US-holiday table now excludes observed federal holidays and projects a weekday holiday at the Saturday rate (Memorial Day 2026 collected $30k against a $107k Monday average). (4) The Spend chip stamped the monthly rewrite time even when a platform's pull had failed (Taboola timed out 3-5 runs a day); it now names the laggard platform and its real time, and the Deals chip prints when the last investigation landed. (5) Per-Deal "② Revenue Collected" header said "cleared"; the code sums cohort cash (reso_conversion.ltv), the header now says so. FIXED IN THE DATA THE SAME AFTERNOON: August platform spend was frozen at the last hourly run of Aug 31 ($2,247,259.20; platforms $2,248,095.65) because autofill refuses closed months; re-finalized, and the script now re-pulls the previous month for the first 7 days of a new month. August REVENUE flipped by $1,410.00 every hour: the API reconcile deleted three payments Logics re-booked and the hourly CSV step re-ingested a stale Aug-31 export from Downloads and re-created them; the export is archived, the ingest now refuses an unchanged file, and August holds at $2,828,547.51 = SOComm. May/Jun/Jul re-pulled for late refunds ($0.00 drift). Month-by-Month qualified calls May 2025-Jan 2026 and Mar 2026 were frozen docs older than the 90-day sync window and read HIGH by 1-92; re-synced from MySQL (Jan 2026 4,177 → 4,093). Company Accolades had captured the dirty August and compared April 2025 against the tracker's count of the same month; rebuilt ($2,828,548 beat June $2,726,833; 1,221 beat 1,020). Case 889239's TI mirrored to Cameron Rutherford in investigations_sold. VERIFIED AND LEFT ALONE: September revenue penny-exact to SOComm at every stamp; MySQL deals = Firestore investigations_sold case-for-case (73 Sep 1-2, 961 Aug); qualified-call definition reproduces every month Apr-Aug 2026 exactly (Aug 3,539; naive 4,241 = + two transfer desks); forecast, pace, budget arithmetic exact; Live Traffic live. · v6.0.2 — "NO SELLING DAYS IN THAT WINDOW YET" WAS FALSE, AND THE CEO CAUGHT IT. The hero card withheld the month-over-month percentage when the benchmark window had zero business days, which is correct: Sep 1-2 (Tue/Wed, 323 payments) against Aug 1-2 (Sat/Sun) produced arithmetically valid, meaningless percentages. But the sentence printed in its place said there were "no selling days in that window yet", which reads as "the benchmark is empty". It was not empty. Aug 1-2 2026 booked $40,808.33 across 112 payments. Payments post on weekends; what those days had none of was BUSINESS days, a fact about the calendar and not about the money. Same failure class as the unlabelled windows fixed in v6.0.0 — the number was right and the words beside it were wrong. The card now prints both real figures and the actual reason the percentage is withheld: "$185,416 vs $40,808 · benchmark window is weekend-only (0 business days), so a % would mislead". The reader can do the division and see for themselves. Verified against Firestore `revenue` under the live gate (canonical id + _from_report, ADServe excluded): Aug 1 Sat 89 pays $33,018.58, Aug 2 Sun 23 pays $7,789.75, Sep 1 Tue 130 pays $90,751.91, Sep 2 Wed 193 pays $94,663.69. · v6.0.1 — PACE TO BEAT LAST MONTH PROJECTED $7.77 MILLION. Swept the other pages for the window fault fixed in v6.0.0 and found a worse one here. On 2026-09-02 the card read AHEAD OF PACE +174.9% and projected September at $7,770,417 against August actual $2,827,138 — because it scaled ONE Tuesday (Sep 1, $90,751.91) by ONE Saturday (Aug 1, $33,018.58) and then multiplied that ratio by the whole of August. The thinnest possible evidence producing the most confident-looking number on the board. A ratio across one or two days is not a pace, and if the two windows fall on different parts of the week they are not comparable at all. The verdict, the percentage and the end-of-month projection are now withheld until there are at least 3 complete days AND at least one selling day on both sides; the card reads TOO EARLY TO CALL and names the weekday mismatch. The revenue figures themselves are untouched and still shown — the money is real, only the extrapolation was not. Mid-month behaviour is unchanged. v6.0.0 — THE COMPARISON NOW SPANS THE SAME DAYS AS THE HEADLINE. It cut on the last COMPLETE day, so on 2026-09-02 the headline read "Sep 1-2, 62 deals" while the comparison read "vs Aug 2026 1-1, 47 vs 1". The two numbers on screen were not the two numbers being divided. That rule existed for a good reason (a half-finished today should not be scored against a full prior day) but it reintroduced the exact fault v5.90.0 was written to remove, just in a different corner of the same card. Per the CMO: it should be the same amount of days last month. The comparison now cuts on TODAY, the printed figure equals the headline, the label names the days, and the part-day is DISCLOSED ("today still running") rather than silently corrected away. The weekday hazard that rule also masked is handled properly by the zero-selling-day suppression added in v5.99.5. v5.99.5 — A PERCENTAGE AGAINST A WINDOW WITH NO SELLING DAYS IS NOT A COMPARISON. Measured 2026-09-02: the card compared Sep 1-1 (a Tuesday, 47 deals) against Aug 1-1 (a Saturday, 1 deal) and printed DEALS up 4600%, REVENUE up 175%. Both arithmetically correct, both meaningless — the benchmark window contains zero working days. Early in a month the day-of-month match can land the two windows on different weekdays, and Aug 1 2026 was a Saturday. The row now reads a dash plus "no selling days in that window yet" instead of a number nobody should act on. Also fixed the guard that would have hidden this: "sells" was built with "momB.curSell && momB.priorSell", so priorSell === 0 — the exact case that matters — was discarded as falsy. It now tests for finite numbers. v5.99.4 — HOTFIX to v5.99.3: the Resolution Sold fallback never fired. loadResoConversion returns ONLY snap.data().months, so resoConv IS the months map and resoConv.soldByMonth was always undefined. v5.99.3 deployed clean, passed its parse test, and the cells stayed blank on the live board. soldByMonth now loads into its own variable instead of being read off a map whose every other key is a month. Caught by re-reading the rendered cells in the browser rather than treating a successful deploy as proof the fix worked — the same lesson as the v5.90.1 style bug and the Accolades permission denial. v5.99.3 — RESOLUTION SOLD was blank for four months. That column reads reso_sold_log/current, fed by a manual "Reso Log" CSV drop, and that feed FROZE on 2026-05-29 — it holds 2023-07 through 2026-05 and nothing since. June, July, August and September rendered "—" on a board people make decisions from, while resolutions_sold had been recording events the whole time (531 in August). The column now falls back to a live event count (reso_conversion.soldByMonth, ADServe excluded) for months the log does not cover, marked "live feed" in the cell so the basis is visible. Deliberately FILL-FORWARD ONLY: the two sources disagree where they overlap (April log 417 vs live 453, May 484 vs 502), so back-filling would silently restate months already reported to the board. The frozen CSV feed itself still needs fixing or retiring. v5.99.2 — THE REVENUE FRESHNESS CHIP HAD BEEN CRYING WOLF FOR 28 DAYS. It picked the newest _report_filename by raw STRING comparison, but two naming formats coexist: "SOCommOnDemand_20260901092532_api" (the headless hourly API pull) and the older "SOCommOnDemand_ondemand_20260803215539" (manual CSV drop). Lexicographically "o" (0x6F) beats "2" (0x32), so the Aug-3 ondemand file outranked every later API pull permanently. The chip read "Revenue feed is 683h old — no fresh SOComm export since Aug 3" and sat red all month while soc-api-ingest was running fine and had written changed docs that same morning at 9:25. Now compares the extracted 14-digit timestamp instead of the filename. A warning nobody can trust is worse than no warning: this one trained everyone to ignore a red chip. v5.99.1 — A STALE SPEND FIGURE NOW ANNOUNCES ITSELF. The Spend freshness chip derived its age from which DAILY spend document existed, which says nothing about when the MONTHLY total was last pulled from the platforms — so a figure hours out of date still rendered "thru Aug 31" and was indistinguishable from a fresh one. Measured 2026-09-01: the board showed $2,247,259.20 for August while Google/Meta/TikTok/Taboola returned $2,248,089.65, and the CMO found the $830.45 gap by pulling the platform APIs himself. autofill-monthly-spend now stamps _synced_at and the chip reads "synced 9:14 AM", turning red past 2h during business hours with a tooltip saying how old it is and what to re-run. _synced_at is a Firestore TIMESTAMP, deliberately not an ISO string: spendForMonthKey sums every value in the document with parseFloat, so "2026-09-01T…" would have added $2,026 to the month. v5.99.0 — Source labelling. (1) The row shown as "Yahoo" is TABOOLA. Its spend is pulled from the Taboola API and reconciles to Taboola's own $39,152.25 for August 2026; there is no Yahoo spend at all. Anyone cutting "Yahoo" would have cut Taboola, and anyone told to scale Yahoo would have had nowhere to spend it. The bucket KEY stays "IRS Fresh Start Yahoo" so ad_spend history is not orphaned — only the display changes, with a tooltip naming the Yahoo-network origin. (2) DEFENSIVE ONLY: the Demand Gen branch now matches /DG|demands*gen/i instead of /DG/. NOTE, because an earlier note here claimed otherwise: this fixes nothing today. Every DG-labelled deal on file reads "IRS Fresh Start Google Form - DG" — uppercase — which the old pattern already matched. Checked against live data: zero August deals mention dg or demand gen in any case, and the new pattern moves no deal and produces no false positive. The DG row reading $9,094.27 against 0 deals in August is therefore a REAL RESULT, not a display fault: Demand Gen has spent about $22,640 since June for 4 deals total. The looser pattern only guards a future lowercase or spelled-out label. v5.98.2 — Accolades correctness, found by testing the page in a real browser rather than a stub. (1) The Firestore read was DENIED in production: company_records is a new collection and no security rule covered it, so the page rendered "could not load (Missing or insufficient permissions.)". Rule added and published by hand via the Rules API — nothing in CI deploys rules, so this class of bug ships silently. (2) A TIE rendered as a win: "7 by Alan Hurtado beat 7 by Stephanie Hughes". Now reads matched / beat / behind by sign. (3) Dropped the tracker seed "Evaeh Lorenz 66" — a misspelling of Nevaeh Lorenz, whose same 66 is already in live data, so the card read as one person beating herself. v5.98.1 — Accolades: added a PRODUCTIVITY record (deals per WORKING agent per day) and taught the renderer to keep decimals on it — Math.round turned 1.81 into 2. The divisor is agents who handled calls that day, NOT agents who sold: the 2025-10-15 announcement divided 60 deals by 26 SELLERS and compared that to 2025-04-14 100 deals over 55 WORKING agents, producing a 27% productivity gain that was not real. On one basis Apr-14 is 1.72 and Oct-15 is 1.08, so October was never a record. Dividing by sellers is self-limiting, since an agent who sells nothing leaves the denominator. A 25-agent floor keeps skeleton days out. v5.98.0 — New COMPANY ACCOLADES page, under Live Traffic in the left nav. Records the company actually celebrates — highest revenue month, most investigations in a day / month / by an agent, most paid-in-full in a day, largest single transaction — each shown NEXT TO THE MARK IT BEAT, because a record with nothing to compare it to cannot be checked (CMO: "revenue record was $3, and then we made $5, that's a record"). Categories are taken from the CMO's own manually-kept Company Accolades sheet rather than invented, and that sheet's pre-2024 marks are seeded in so history predating our tables is not lost; a live figure supersedes a seed the moment it exceeds it. Also lists every officer who beat their own personal best this month. Source: company_records/current ← ad-intel company-records-precompute.mjs. v5.97.0 — Two fixes. (1) The "Compare to" dropdown could DISPLAY one month while the cards computed another. benchMonthOffset defaults to 1 (last month) and is persisted nowhere, but the select had no autocomplete=off, so Chrome restored the previously chosen option on reload without firing a change event. Measured 2026-08-31: the control read "June 2026" while every hero row computed July ($2,577,453 vs $2,103,521, labelled "vs Jul 2026 1-30"). Same failure class as the unlabelled windows fixed in v5.90.0 and v5.95.0 — a label disagreeing with its number. The select now opts out of restoration, and buildBenchOptions reconciles the variable to whatever the control actually shows. (2) The v5.96.0 per-selling-day figures rendered with mismatched precision on Deals — "45.8 vs 44.273" — because fmt() does not round. Per-day values now round to the dollar for money and one decimal for counts. v5.96.0 — The selling-day note now states the RATE, not just the divisor. It has been printing "20 vs 22 selling days" under a percentage computed on raw totals, leaving the reader to divide. Against Jun 2026 that concealed a sign flip: Aug 1-30 showed ▼6% ($2,577,453 vs $2,728,618) while per selling day it was ▲4% ($128,873 vs $124,028), because August had 20 selling days to June's 22 — the board said "behind" on the record month while production per working day was ahead. Identical to the DEALS card bug fixed in v5.91.0, which added the disclosure but never used it. Revenue and Deals now append "▲ 4% per selling day" with both sides shown. Qualified Calls is deliberately excluded: its MoM window is re-capped to the calls watermark, so those day counts do not describe it. v5.95.0 — The three headline numbers now NAME their own window. The headline runs through today while the comparison rows stop at the last complete day, so on 2026-08-31 a 1-31 figure sat directly above rows labelled 1-30 and only the small rows said which window they meant. The CMO read $2,640,954.61 off the board against his own $2,577,453 book, concluded the board was wrong, and reported the month incorrectly — both numbers were right, they were different windows. Each hero card now prints its window under the value, e.g. "Aug 1-31 · through today", cut on the real data boundary so mid-month reads "Aug 1-26" and a finished month reads "Jun 1-30". Numbers, queries and gates unchanged. v5.94.0 — Trends now includes Spend grouped by platform, with This Month MTD, Last Month, Last 2 Months, 6 Months, 1 Year, and All Time windows. Completed-month windows exclude the current partial month. Total spend is shown back to the historical tracker floor; platform rows begin in Jan 2026, with older platform cells left blank because no defensible split exists.
v5.93.0 — The hero comparison rows now print BOTH sides of the division, not just the benchmark. The headline is month-to-date through TODAY while the comparison runs through the last COMPLETE day, so on 2026-08-26 the card showed $2,059,988 beside $2,055,836 and said "down 5%" — the compared figure (Aug 1-25 = $1,955,882) was nowhere on screen and the percentage looked wrong. Rows now read "$1,955,882 vs $2,055,836" so the arithmetic is checkable at a glance. v5.92.0 — Audit fixes, wave 1. (1) BUDGET PACING treated today as spent AND as remaining: the run-rate divided 18 days of spend by 17 days, while "days left" still counted today as available even though its spend was already subtracted. Both errors pushed toward the red ABOVE warning. Measured 2026-08-26: card claimed 11,999/day pace vs 1,504/day left (1.82x over); honest figures are 05,777 vs 2,005 (1.29x). Today is now ELAPSED on both sides. (2) REVENUE and DEALS headlines rendered /usr/bin/bash.00 and 0 when their feed failed to load, making a total outage look like the worst month in company history; Spend already guarded this. Both now show a dash when nothing loaded, while a genuinely empty window still reads zero. (3) PACE TO BEAT LAST MONTH compared this month INCLUDING today against last month COMPLETE and printed "same days". July 26 was a Sunday, so the headline swung ~5 points across one day with nothing changing underneath and the verdict could walk BEHIND -> ON -> AHEAD. Both sides now end on the last complete day, matching the hero card, and every label names the real window instead of printing a day the prior month may not have. v5.91.0 — Diagnostic sweep fixes. (1) The selling-day note now appears on ALL THREE hero cards, not just Revenue. Measured 2026-08-26: the DEALS card read "▼6% vs Jun 1-25" (789 vs 839) while deals per selling day were 46.4 vs 44.2, UP 5.1% — August had 17 selling days against June's 19. The sign flipped, and the disclosure was on the one card least affected, since deals land Mon-Fri. (2) The YoY row now names its window ("vs last yr 1-25") instead of a bare "vs last year" beside a row that names its bounds. (3) .da-filter-btn had NO css rule at all, so the Deals-per-Agent Daily/Weekly/Monthly/Range buttons rendered as raw OS buttons with nothing marking the active one. (4) .rt-stale lost a specificity contest to .section-head .meta, so the "GA4 feed stopped" warning painted the same muted grey as the healthy state. (3) and (4) are the same ancestor-chain bug class as the v5.90.0 .ctx miss. v5.90.1 — HOTFIX to v5.90.0: the "17 vs 19 selling days" note rendered as a HEADING. `.ctx` was only ever styled under `.hero-yoy`, but renderCompare writes into `.hero-compare`, so the note inherited 14px full-white body text and read louder than the numbers it annotates. Now styled under `.hero-cmp-row` as an 11.5px muted footnote. The pre-deploy layout check missed it because the probe markup was wrapped in `.hero-yoy` rather than the container the card actually uses — a test that did not reproduce the real DOM. Numbers unaffected. v5.90.0 — Hero comparisons now run BOTH sides through the last COMPLETE day, matched on DAY OF MONTH. CMO 2026-08-26: the card read "▲3% vs Jun 2026" while his own book had Aug 1-25 $1,955,882 BEHIND Jun 1-25 $2,055,836 — both figures were right, they were just different windows, which is the worst kind of wrong. Two causes. (1) The numerator was the through-TODAY headline, so a half-booked today was scored against a complete prior-month day. (2) The benchmark matched on BUSINESS DAYS ELAPSED, which is defensible but is not the comparison the business makes; it put June's cut at the 24th while the label just said "vs Jun 2026". Now: numerator = same window as the benchmark (Aug 1-25), benchmark = prior month 1-25, and the label SAYS the window ("vs Jun 2026 1-25") so it can be reconciled against anyone's own numbers. August correctly reads ▼5%. The reason business-day matching existed is kept, not discarded — when the two windows hold a different number of selling days the card now says so ("17 vs 19 selling days") instead of silently correcting for it. The REVENUE headline itself is unchanged: it still shows every dollar booked so far this month. v5.89.2 — Column reorder is now drag-and-drop: grab the ⠿ handle and drop a column anywhere (the ▲▼ arrows still work for fine moves). Much faster than clicking arrows to move a column across the table. v5.89.1 — Columns dropdown now also REORDERS: ▲▼ arrows next to each column set the order (first→last), persisted; Reset restores defaults. The 6 same-month/recurring columns move as one block; Revenue Month stays pinned first. v5.89.0 — Month-by-Month table: new "⚙ Columns" dropdown to show/hide any column (persisted across reloads); replaces the single PS/PN toggle, which is migrated in. Column reorder is the next step. v5.88.6 — Reverted the v5.88.5 global zoom (0.8) back to 100% — it made the dashboard hard to read. v5.88.5 — Collapsed the on-page changelog (it was rendering the full version history as a wall of text at the bottom of the page) down to just the version number; full history kept in a hidden element so nothing is lost. Also added a global zoom (0.8) so more of the dashboard fits on one screen. v5.88.4 — Sources table Spend column is now penny-exact ($XXX,XXX.XX) — both the per-source rows and the Total — so it reconciles to each ad platform's UI (Google Ads, Meta, TikTok, Taboola) to the cent. v5.88.3 — Sources table column reorder: Spend now sits right after the Source name (before Deals), so the row reads Source → Spend → Deals → … → CPA → ROAS. Applies to both the By-Campaign and Sources views and the Total row. v5.88.2 — REVENUE headline is now penny-exact ($X,XXX,XXX.XX): the value, the ADServe/total sub-line, and the weekday-rate breakdown all show cents so it reconciles to the SOComm total. (EOM forecast stays whole — it's a projection, not a reconciled figure.) v5.88.1 — Trends table: the Source column is now frozen (sticky-left) so it stays visible when scrolling the day/month columns horizontally. v5.88.0 — Trends now has a granularity selector (Daily / Monthly / 6 Months / 1 Year) — trend ANY metric (CPA, ROAS, Deals, Avg Debt, PIF%, Revenue) per source at any resolution, same green/red heatmap. Daily uses its own window chips (This Month / 30d / 60d / 90d) and scrolls horizontally. Daily CPA & ROAS per source are powered by a NEW daily per-source spend feed (Google campaign-split-by-day → ad_spend_daily_source, refreshed hourly + nightly, reconciled to the monthly m_ doc to the dollar). Daily PIF% = cumulative paid-in-full to date (same-day cash is ~always 0, so a same-day rate would read 0%). v5.87.0 — Forecast + headline now speak the same business-day language. The Revenue Forecast card splits "days remaining" into biz vs weekend days and adds an "at this month's biz-day pace" cross-check (weekday-rate × remaining weekdays + weekend-rate × weekend days) so it reconciles with the headline instead of reading low next to it. The headline's $/biz-day is now a TRUE weekday rate — weekday cash only (weekends stay in the TOTAL but not the per-weekday velocity); it was folding weekend cash in, which inflated the rate. All three reads of the month (headline pace, biz-day pace, DoW forecast) now land within ~3% of each other, all a few points under May's record. v5.86.0 — Revenue freshness chip now flags RED if the latest SOComm export is more than 14h old during business hours (Mon–Fri, 8 AM–7 PM) — it was a flat 30h, which let a 15h-stale feed sit un-flagged on a Friday morning and read as "stuck". Off-hours/weekends keep the looser 30h guard so it doesn't nag overnight. Hover the Revenue chip when red for the data age + a "drop a fresh export" reminder. v5.85.0 — Toggle on the Month-by-Month table to collapse the Paid Something + Paid Nothing columns (keeps Paid In Full). Checkbox in the legend bar; preference remembered across reloads (localStorage). v5.84.0 — Avg Debt (Resolved) is now the tax debt AT the resolution sale (POINT-IN-TIME), not the current value. Per CMO: it's what the debt was when we sold the resolution. Computed from the IRS Logics CaseActivity "Tax Liability changed to X" history, anchored to the "Zapier Resolution Sold" date — reverting any later correction (e.g. case 102019: sold Nov-2024 at $50k, corrected to $42,764 in Oct-2025 → the column shows $50k). Source: cohort_resolved_debt/current ← cohort-resolved-debt-precompute.mjs. v5.83.0 — New column: Avg Tax Debt (Resolved) — the average IRS debt of the deals that converted to a resolution, next to Resolution Rate. Confirms the quality signal: resolvers carry meaningfully more debt than the cohort overall (e.g. Oct 2024 $34.7k resolved vs $27.2k all; sub-line shows the % delta). Same source as Avg Tax Debt: MySQL deals.Amount_Owed (2024-10+) + IRS Logics CaseInfo.TaxLiability (2023-2024, re-pulled). Small-sample guarded (≥10 resolvers). v5.82.0 — The LAST two columns for 2023–2024: Paid In Full and TI Sold→Reso Opp %. Paid In Full (+ Paid Something/Nothing, now all coherent) from IRS Logics SUCCESS payments per TI Log case vs the Investigation invoice fee — same method as 2025+ (PIF ~16–25%, PS ~59–71%). Reso Opp % (same-month) from MySQL caseStatusTimeline "Ready To Present" events joined to the TI Log cases — same source the live metric uses (~4–13% same-month). The 2023–24 cohort table now matches the 2026 rows column-for-column (only Jun 2023 stays sparse — PARTIAL). Sources: cohort_pif/current ← cohort-pif-precompute.mjs · resoOppSame in cohort_ltv. v5.81.0 — Avg Tax Debt + Contracted / % Collected / Projected / Projected ROAS for 2023–2024, pulled from IRS Logics per TI Log case (23,100 API calls): CaseInfo.TaxLiability → Avg Tax Debt, Billing/CaseInvoice → Contracted (company, excl AdServe), joined to cleared revenue. Avg debt runs ~$23k–$35k; ~40–53% collected (matching the ~50% mature rate). Avg Tax Debt falls back to this pre-Oct-2024 (MySQL debt_summary wins where present); Contracted/Projected fall back pre-2025. Jun 2023 skipped (PARTIAL). Source: cohort_irslogics/current ← cohort-irslogics-precompute.mjs (nightly). v5.80.1 — HOTFIX: v5.80.0's Scale Score still read pm.pif directly when pmTotal>0, but pre-2025 now sets pmTotal from cohort_ltv with pm undefined → render threw "cannot read pif", blanking the board. Guarded the pm reference. v5.80.0 — More 2023–2024 cohort columns from the TI Log × all-time revenue: Paid Something, Paid Nothing, Resolution Rate, and Avg Reso Fee now populate for Jul 2023–Dec 2024 (mature cohorts run ~35–44% resolution rate, ~$3.0k–5.3k avg reso fee). Paid Something/Nothing = cohort cases that paid any / no all-time company revenue; Resolution Rate + Avg Reso Fee = cases with a resolution-type payment and their reso revenue. Paid In Full stays blank pre-2025 (needs per-case fee data); Avg Tax Debt + Contracted/Projected coming next from IRS Logics. v5.79.0 — Real LTV + Cohort ROAS for 2023–2024. Joined the CMO's TI Log (11,550 investigations sold Jun 2023–Dec 2024, by Case ID) to all-time company revenue → per-cohort lifetime value, filling the previously-blank LTV and Cohort ROAS columns. The mature 2023–24 cohorts run ~5–6x Cohort ROAS (LTV ÷ ad spend). June 2023 is skipped — the log starts 6/20 so it only covers 22% of the month (PARTIAL), which would understate ROAS. ~37–42% of cases have no revenue on file (didn't convert), so LTV is a realized floor. Sources: ti_log_sold/current ← ti-log-ingest.mjs · cohort_ltv/current ← cohort-ltv-precompute.mjs (TI Log × revenue). v5.78.2 — Filled the Jan–Apr 2025 gap in Qualified Calls / Cost-per-Call / Closing %: live call-counts only begin May 2025, and the tracker fallback was bounded to pre-2025, so those four months showed blanks. Loosened the rule — the Trend Tracker now fills ANY funnel cell the live feed is missing (deals still stay live for 2025+). v5.78.1 — Reverted the v5.77.2 column reorder: the Month-by-Month columns are back in their ORIGINAL order (Revenue Month · Ad Spend · Qualified Calls · Cost/Call · Closing % · Deals (TI) · Reso Opp % · Resolution Sold · CPA · Avg Debt · PIF/PS/PN · Revenue Per TI · … · Total Revenue · blue/green split · … · Scale Score). The reorder only existed to hide the pre-2025 blanks; now that the Trend Tracker backfill (v5.78.0) fills those leading columns back to 2023, the familiar order is restored AND fully populated. v5.78.0 — Pre-2025 history filled from the CMO's manual "Trend Tracker". The Month-by-Month funnel columns (Deals · Ad Spend · Qualified Calls · Cost/Call · Closing % · CPA · Resolutions) were blank before 2025 because ad spend (Jan 2025+), call counts (mid-2025+) and the deals/debt table (Oct 2024+) don't reach back. The tracker does — funnel to 2023, spend to 2022 — and (verified) its Investigations count is MORE complete than the live feed, which undercounts ~3% and is empty Jan–May 2023. Per CMO decision the tracker is the deal + funnel source for pre-2025; live stays authoritative 2025+. Cost/Call, Closing %, CPA are DERIVED from the tracker's deals/spend/calls so they reproduce its numbers exactly. Revenue still comes from the live system. Source: funnel_history/current ← ad-intel funnel-history-ingest.mjs (re-run on a fresh tracker export). v5.77.2 — Month-by-Month columns reordered so the data that goes back to 2023 LEADS: Deals (TI), Total Revenue, the same-month vs recurring split, Revenue Per TI, Resolution Sold, LTV — then the spend-derived / recent-only columns (Ad Spend, CPA, Cost/Call, Closing %, Avg Tax Debt, PIF) follow on the right. Old rows no longer open onto a wall of blanks; nothing was removed, just resequenced. The pre-2025 blanks are real data gaps, not a display bug: ad spend only exists from Jan 2025 and the deals/debt table starts Oct 2024 (verified — no debt source reaches 2023; Avg Tax Debt precompute pinned to its true Oct-2024 floor so it never ages off). v5.77.1 — Wider tables: inside the tabbed layout the content container kept the global 1200px max-width + auto-centering, so on wide monitors it floated in the middle, leaving a big gap between the left nav and the table. Now the container fills the space next to the sidebar (max-width removed, flush-left), so the Month-by-Month and Per-Deal tables get the full width. v5.77.0 — Left-nav tabs: the page is split into Dashboard (headline → forecast → ad spend → sources), Staffing & Capacity, Per-Deal Economics, and Month-by-Month Revenue. Each is its own page; hard refresh always lands on Dashboard. All sections still render on load (just hidden until selected), so nothing slows down. v5.76.1 — fix: cohort window boundary was off by one (May 2025 fell in a gap between the precompute and the live window). Now contiguous — every month from Jan 2023 to now. v5.76.0 — Month-by-Month cohort table now shows back to January 2023 BY DEFAULT, fast: deals + revenue + same/recurring split for older months come from the nightly `cohort_history` precompute (verified to match the live computation to the penny), so no slow client load and no button. CPA / Avg Debt / LTV / Cohort ROAS stay blank before 2025 (no ad-spend / precompute data that far back). Per-Deal Economics table stays at 13 months. (Replaces the v5.75 on-demand "Extend to 2023" button.) on demand, loads deals + revenue back to Jan 2023 (rolling 13-month window otherwise, kept fast by default). CPA / Cohort ROAS stay blank before 2025 — ad-spend data only exists from Jan 2025; deal+LTV columns populate from 2023 (investigations_sold + revenue). v5.74.0 — Staffing panel now leads with the ANSWER: a hero banner stating the action + how many + how soon (e.g. "HIRE ~8 · start now · ~4/month after"), computed in the precompute (net seats to clear the peak-drop, grossed up for ramp wash-out + throttled demand). The capacity wall, deals/agent dial, and per-agent table collapse under a "show the evidence" toggle so the read is clean. v5.73.0 — Staffing & Capacity panel: Hire/Hold/Cut decision lights from MySQL (Processed_call + deals → staffing_capacity/current, nightly). Shows TIs/agent/day vs the 3 target, the capacity wall (drop rate rises with call load while agents-live max out + peak concurrency + live-vs-callback), the deals/agent stop-hiring dial, the 3-TI/day lead gap, and per-agent production with non-producer flags. Fully guarded render (can't break the board). v5.72.0 — Demand Gen on the board: "IRS Fresh Start Google - DG" gets its own pinned Sources row + spend bucket ("FSR - Demand Gen - TI (rebuilt)" 23881397484, landing /google-gettaxreliefnow/, phone 888-800-9013, queue 1_FSI_Google_DG — forms AND calls attribute distinctly; "Google Form - DG" no longer folds into plain Google). v5.71.1 — HOTFIX: v5.71.0's dead-collection removal missed one reference to the removed `call` variable in loadAll's partial-load check — ReferenceError after data load, dashboard never rendered (caught by CMO 2026-06-12 08:20, prod down ~14h). v5.71.0 — Label-truth batch: cohort Ad Spend tooltip no longer claims "Manual entry" (auto, hourly) · static header says "refreshed hourly" not "nightly" · hardcoded "~52%" collection rate and "$259→$641" narrative removed from tooltips (live rate is computed nightly) · Daily CPA date picker no longer hides pre-Mar-9 data (fixed 2026-03-03 start) · Calls freshness chip no longer cries wolf every afternoon (staleness measured from end of synced day) · dead call_counts_daily collection no longer downloaded on every page load. (v5.70.0 one projection per metric.)