Skip to main content
All marketing & content articles

Marketing ROI grid — what each channel actually pays back

Track ad spend per channel monthly and see Spend / Leads / Bookings / Revenue / ROI per source. First-touch attribution, no setup.

Updated 2026-05-01

Every contractor we've talked to has the same blind spot: they spend money on Google Ads + Yelp + Angi + GBP every month and have NO IDEA which one actually pays back. /portal/marketing fixes that with a single grid: Spend × Leads × Bookings × Revenue × ROI per source.

How to use it

  1. 1
    Add your sources

    Go to Settings → Lead sources & ad spend (or click "Manage sources & spend" from the top of the ROI page; direct URL is /portal/marketing/sources). 8 channels are seeded by default: Google Ads, LSA, Facebook Ads, Yelp, Angi, GBP, Word of Mouth, Direct. Add new ones (Nextdoor, Thumbtack, mailers) as needed. Archive old ones — past attribution preserved.

  2. 2
    Enter your monthly spend

    On the same page, click any month's cell next to a source and type the dollar amount. We store one row per (source, month) so YTD reports compute against actual month-by-month spend, not today's UI value.

  3. 3
    Read the grid

    /portal/marketing shows Spend / Leads / Bookings / Revenue / ROI per source for the period (this month / last month / 90d / YTD). ROI is color-coded: green for ≥5x, neutral for 2-5x, red below 1x.

How attribution works

When a lead comes in, we tag the row with the lead_source_id matching whatever channel it came from (UTM params for web, Hannah's "how'd you find us?" for calls, Direct for the booking widget). Bookings count by their tagged source. Revenue is FIRST-TOUCH: paid invoices credit the source on the customer's first attributed appointment — so a returning customer doesn't double-count under their original source.

What the warning band means

If a source has spend > $0 but zero bookings in the period, /portal/marketing surfaces a red banner at the top — "money out, nothing booked. Worth investigating before next month's budget runs." That's usually the contractor's #1 "oh, we should turn THAT off" moment.

ROI ≥ 5xPour more in. This channel is printing money — test 2x your monthly budget next cycle and see if the math holds.
ROI 2-5xHealthy. Most paid ad channels live here. Keep it where it is unless you have a specific reason to move.
ROI 1-2xMarginal. Costs are eating most of the revenue. Optimize ad copy + audience targeting before pulling the budget.
ROI < 1xLosing money. Pull the spend, run a 30-day "organic only" experiment, and re-decide whether to come back to it.
Setup is fast

Brand-new clients get the 8 default sources auto-seeded the moment they finish onboarding. You don't have to import anything; you just add your monthly spend numbers and the grid lights up.

Manual call attribution coming next

Today only widget bookings + UTM-tagged form submissions auto-tag a source. Voice calls have a `source` text column populated by the AI but we don't auto-resolve to a lead_source_id yet. The next pass will let Hannah ask "how'd you find us?" and map the answer to a source — until then, you can manually tag voice calls from /portal/calls if it matters.

Ready to try this in the actual product?

14-day free trial, no card charged for 14 days, cancel anytime.

More marketing & content articles