Two CPAs live in this account. One is what Google Ads reports about itself. The other is what the money actually bought.
Cost per booked job (a booked appointment in ServiceTitan) is the one number that means the same thing across every P3 OpCo, no matter how each account's tracking is wired. $361 is 2 Sons' baseline, locked as of this window, and it is the number we drive down from here. For context, the portfolio blended baseline across all three priority accounts is $295 (170 booked jobs on $50,178), so 2 Sons is the account with the most ground to make up and the most to gain.
Read this first. Every claim below is expanded, with the evidence, in the sections that follow. Changes now roll out as items clear the sign-off list on the hub, and each push gets logged there.
The one-line version: fix tracking first so the bid signal is honest, then lift non-brand Quality Score and budget together (the landing page rebuild is half of that), then clean the structure and negatives. In that order.
The reported $133.50 CPA is not a real number. It counts the same phone call two or three times, because three separate call-tracking actions across three phone numbers are all set as primary. Anchored to ServiceTitan booked jobs, which the account already records and which sum to 51 in Google Ads, the cost per booked job reads $361. ServiceTitan itself shows 79 booked jobs for July, so the real number is likely near $233 once the import gap closes. It is not a crisis; it is a starting line we can finally see. The ServiceTitan figures here are the numbers recorded in Google Ads through the offline import, pending reconciliation with ServiceTitan's own reports.
| Metric | Reported in Google Ads | ServiceTitan reporting |
|---|---|---|
| Spend (30d) | $18,423 | $18,423 |
| "Conversions" | 138 | n/a |
| Booked jobs | n/a | 51 (45 call ext + 6 website) |
| Cost per event | $133.50 reported CPA | $361 per booked job |
| Campaign | Spend | Share of spend | Reported conv | Share of conv | Reported CPA |
|---|---|---|---|---|---|
| 2Son-SEM-Brand-Seattle | $7,810 | 42% | 89 | 64% | $88 |
| 2Sons-SEM-LG-Plumbing (non-brand) | $7,601 | 41% | 26 | 19% | $292 |
| 3x PMAX Retargeting (paused mid-window) | $3,012 | 16% | 23 | 17% | n/a |
Strip brand out and the picture changes hard. Brand's $88 CPA looks great, but brand is mostly capturing demand that already exists: the top brand search term "2 sons plumbing" alone spent $3,469 for 162 clicks. That is people who were going to call 2 Sons anyway. The brand campaign already shows for nearly every brand search, and it has an $800/day budget it does not use (it actually spends about $260/day), so most of that budget sits idle.
The non-brand campaign is the actual customer-acquisition engine, and it is running at a $292 reported CPA while showing for only about 1 in 6 relevant searches. That is what the account looks like with brand stripped out, on reported numbers. Growth has to come from here, and it is the most constrained part of the account.
Offline conversion imports from ServiceTitan are the backbone of long-term optimization on this account. They already flow in: 51 booked jobs landed in Google Ads last month, matching ServiceTitan exactly. The problem is that bidding ignores them, because they sit marked secondary while raw call trackers hold the primary slot. The fix is a settings change, not a rebuild: make bidding use the booked jobs. Later this same pipe becomes job-value import and revenue bidding, so the account can bid toward dollars, not just job counts.
21 conversion actions are enabled and 6 are primary. The primary goal is a stack of call trackers spread across three different phone numbers, while the real money event (ServiceTitan booked job) sits secondary. A single call gets counted through whichever number it hit, so reported conversions (138) are about 2.7x the ServiceTitan-reported booked jobs (51).
The two ServiceTitan Booked Job actions (Call Extension + Website) become the only primary goal. Together they are "a booked job," split only by source, and they sum to 51 for the window, giving a clean $361 cost per booked job. At 51/month this clears the ~30-conversions-per-month threshold Maximize Conversions needs to bid well, so we do not need a second primary to prop up volume. Everything else goes secondary: still recorded and visible for insight, not counted in the bidding goal.
Why no call action stays primary: adding a call action alongside booked jobs would re-introduce call-to-job double counting (the same call counts once as a call and again when it books) and push reported volume back up, which muddies the $361 booked-job number. Because booked-job volume already clears the bidding threshold, the cleaner answer is booked-jobs-only as primary. This matches how we set up Pride and Rolland.
Which of the three phone numbers survives: we keep (206) 710-2259 as the one live tracking number in the ads and on the site, and retire the other two (the "Joe's 2 Sons" ad-call number and the (206) 487-1757 website number), since the two AD_CALL trackers are duplicates on different numbers. Three numbers on one business fragments the call data and makes any single report wrong. The de-duplicated "ServiceTitan Calls Conversion Action" (id 7049322959) stays as the designated secondary backup: if booked-job volume ever dips below ~30/month, that action is the bridge we promote to primary, not one of the raw Google call trackers.
| # | Action | Type | Current | 30d vol | Proposed | Why |
|---|---|---|---|---|---|---|
| 1 | ServiceTitan Booked Job (Call Extension) | Upload calls | Secondary | 45 | PRIMARY | Real money event, phone side. Half of the 51. |
| 2 | ServiceTitan Booked Job (Website) | Upload clicks | Secondary | 6 | PRIMARY | Real money event, web side. Other half of the 51. |
| 3 | Calls from ads (206) 710-2259 | Ad call | Primary | 71 | SECONDARY | Raw call, double counts vs booked jobs. This number stays live; the action goes secondary. |
| 4 | Joe's 2 Sons Ad Phone Call | Ad call | Primary | 49 | RETIRE # | Duplicate ad-call on a second number. Retire the number, mute the action. |
| 5 | Calls to a number on the website (206) 487-1757 | Website call | Primary | 18 | RETIRE # | Third phone number. Consolidate to one; mute the action. |
| 6 | Clicks to call | Google-hosted | Primary | 9 | SECONDARY | Button-click proxy, not a real outcome. |
| 7 | ServiceTitan Calls Conversion Action | Upload clicks | Secondary | 10 | BACKUP | De-duplicated call action. The bridge to primary only if booked-job volume drops below ~30/mo. |
| 8 | ServiceTitan Inbound Call - Extension | Upload calls | Secondary | 151 | SECONDARY | Counts all inbound calls, not just ad-driven. Too broad to bid on. Keep for insight. |
| 9 | ServiceTitan Inbound Call - Website | Upload clicks | Secondary | 12 | SECONDARY | Same, web side. |
| 10 | ServiceTitan Lead - Extension | Upload calls | Secondary | 86 | SECONDARY | Upstream of a booked job. Insight only. |
| 11 | ServiceTitan Call Extension Completed Job Conversions | Upload calls | Secondary | 42 | SECONDARY | "Completed" is downstream of booked. Overlaps booked jobs. Insight only. |
| 12 | ServiceTitan Completed Jobs Conversion Action | Upload clicks | Secondary | 6 | SECONDARY | Same, web side. Insight only. |
| 13 | ServiceTitan JVP (Call Extension) | Upload calls | Secondary | 44 | SECONDARY | Job value/potential signal. Overlaps booked jobs. Insight only. |
| 14 | ServiceTitan JVP (Website) | Upload clicks | Secondary | 6 | SECONDARY | Same, web side. Insight only. |
| 15 | Contact 2023 | Web form | Secondary | 4 | RETIRE | Legacy duplicate of the thank-you form. Archive. |
| 16 | Submit lead form (thank-you, no slash) | Web form (codeless) | Secondary | 4 | SECONDARY | Keep this single thank-you form as the web-lead signal. |
| 17 | Submit lead form (thank-you/, trailing slash) | Web form (codeless) | Secondary | 4 | RETIRE | Exact duplicate of #16 (same page, trailing slash). Counts the same submit twice. Archive. |
| 18 | Emergency Sewer Repair Lead Form | Web form | Secondary | 0 | SECONDARY | No volume this window. Keep, monitor. |
| 19 | 2 Sons Plumbing - GA4 (web) BookingBooked | GA4 page view | Secondary | 0 | SECONDARY | GA4 page-view proxy. Keep for GA4 continuity, never primary. |
| 20 | local_services_phone_lead | LSA | Primary | 0 | SECONDARY | LSA campaign is paused. Mute now; revisit if LSA turns back on. |
| 21 | local_services_message_lead | LSA | Primary | 0 | SECONDARY | Same. |
Net effect: primary goes from 6 muddy call actions to 2 clean booked-job actions. Three phone numbers collapse to one. Two duplicate form actions are retired. Nothing about ad delivery breaks; we are re-labeling which actions count, not removing tracking.
Non-brand is the growth engine, and its ads show for only about 1 in 6 relevant searches, while brand shows for nearly every brand search. It misses the rest two ways at once: the daily budget runs out (that costs about a third of the chances to show), and weak Quality Score and bids keep the ads out of most of what remains, even when there is money left.
| Campaign | Daily budget | Actual daily spend | Shows for (share of relevant searches) | Missed because budget ran out | Missed on Quality Score and bids |
|---|---|---|---|---|---|
| Brand | $800 | ~$260 | 96% | 0% | ~4% |
| Non-brand | $300 (shared) | ~$253 | 17% | 34% | ~49% |
Non-brand keywords average Quality Score 4.2, with 14 of 22 scored keywords at 4 or below. Brand averages 8.3. Low Quality Score is why non-brand clicks cost about $51 each (versus $22 on brand), why the ads show for only about 1 in 6 relevant searches, and why single clicks on terms like "auburn plumbers" ($277 for 2 clicks) and "24 7 plumbers" ($187 for 1 click) are burning the budget.
A rebalance has two moves, and both are needed:
Budget without Quality Score just buys more $51 clicks. Quality Score without budget still leaves the ads showing for only about 1 in 6 relevant searches. We do them together.
The "Landing Page Test" campaign is enabled but has spent $0, because it shares the same budget (ID ...220844) as the non-brand campaign. Two campaigns on one shared budget compete for the same dollars, and the established non-brand campaign consumes them. The LP test cannot get incremental spend without starving non-brand. The fix: give it its own budget and point it at the new mock, or pause it until the LP rebuild is ready. Right now it is a test that cannot run.
Three Performance Max retargeting campaigns (Sewer & Drain, General Plumbing, Water Heater) spent $3,012 for 23 reported conversions before being paused. The change history shows three campaign edits on July 20 at 10:28am by p3servicesmarketingteam3@gmail.com (a shared Gmail account, via the web UI), lining up exactly with the three pauses.
Our read: the pause was probably the right call on the merits, but it was done blind. Retargeting is a weak fit for emergency plumbing; someone with a burst pipe calls the first credible result, they do not need to be followed around the web. PMAX retargeting also tends to claim credit for conversions that brand or direct would have captured anyway, which inflates its apparent 23 conversions. The problem is process, not outcome: no documentation, a shared internal login, no before/after measurement, so we would not know if it helped or hurt. When P3 gives the go-ahead, we would formalize the decision (keep it paused, redirect that ~$3,000/month toward non-brand) and note it, so the next person understands why.
The top search terms carried $2,434 of zero-conversion spend in 30 days, about $29,600/year at this rate. The competitor-name group is in today's push wave; the rest waits on the business profiles.
The real leak is competitor names and commercial HVAC. Everything below is genuinely wasteful regardless of geography.
These name places outside the targeted footprint. Add to General Negatives - Master as phrase match (the city word is the signal). Kitsap and Bremerton are across Puget Sound in Kitsap County, so these are true bleed; confirm before adding if 2 Sons services the peninsula.
| Term | Match type | Set | Evidence (30d) |
|---|---|---|---|
| spokane | Phrase | General Negatives - Master | "action drain spokane" $45, 1 click, 0 conv |
| orcas | Phrase | General Negatives - Master | "morris plumbing orcas" $88, 1 click, 0 conv |
| kitsap | Phrase | General Negatives - Master | "swift plumbing kitsap" $14, 0 conv |
| bremerton | Phrase | General Negatives - Master | "plumbing bremerton" $20, 1 click, 0 conv |
Rival plumbers leaking through broad match. A Competitors set already exists (397 members); these slipped past it. Add as phrase match to Competitors. Hold out for review: "nw sundance services" ($95, 1 conv) and "trusted plumbing and heating," "van's plumbing," "erik d plumber," which each recorded 1 conversion.
| Term | Match type | Set | Evidence (30d) |
|---|---|---|---|
| harolds plumbing | Phrase | Competitors | "harolds plumbing auburn wa" $80, 0 conv |
| ayers plumbing | Phrase | Competitors | $67, 0 conv |
| psr mechanical | Phrase | Competitors | "psr mechanical seattle" $61, 0 conv |
| prokash plumbing | Phrase | Competitors | $59, 0 conv |
| quality plumbing ballard | Phrase | Competitors | $57, 3 clicks, 0 conv |
| cahill's plumbing | Phrase | Competitors | "cahill's plumbing & heating" $53, 0 conv |
| mitchel plumbing | Phrase | Competitors | $44, 0 conv |
| hd partners | Phrase | Competitors | "hd partners seattle" $33 + $18, 0 conv |
| hunt's plumbing | Phrase | Competitors | "hunt's plumbing tacoma" $29, 0 conv |
| collier plumbing | Phrase | Competitors | $24, 0 conv |
| royal rooter | Phrase | Competitors | "royal rooter plumbing" $21, 0 conv |
| john the plumber | Phrase | Competitors | "john the plumber near me" $19, 0 conv |
| joe the plumber | Phrase | Competitors | "joe the plumber near me" $18, 0 conv (not the 2 Sons owner "Joe") |
| rick wilson plumbing | Phrase | Competitors | $12, 0 conv |
| pelican plumbing | Phrase | Competitors | $11, 0 conv |
| jd plumbing | Phrase | Competitors | "jd plumbing & fire protection" $9, 0 conv |
| sundance plumbing / nw sundance | Phrase | Competitors | "sundance plumbing" $8 + "nw sundance services" $95 (1 conv, review before adding) |
| splash plumbing | Phrase | Competitors | "splash plumbing seattle" $7, 0 conv |
| pars plumbing | Phrase | Competitors | $5, 0 conv |
| 2 guys plumbing / 3 sons plumbing | Phrase | Competitors | Look-alike brands, ~$14 combined, 0 conv |
2 Sons is residential-focused, but a Commercial Plumbing ad group does convert, so we do not blanket-negative "commercial." Only the commercial HVAC queries are clear waste. Add to Different Service or Trade as phrase.
| Term | Match type | Set | Evidence (30d) |
|---|---|---|---|
| commercial hvac | Phrase | Different Service or Trade | "commercial hvac companies seattle" $140; "best commercial hvac companies" $80; $220 total, 0 conv |
Low purchase intent, comparison and cost research. Add to Costs, Discounts (currently only 1 member) and DIY (currently only 1 member). Both sets are nearly empty and need building out.
| Term | Match type | Set | Evidence (30d) |
|---|---|---|---|
| replacement cost | Phrase | Costs, Discounts | "garbage disposal replacement cost" $35; "labor cost to replace garbage disposal" $14; 0 conv |
| how much does | Phrase | Costs, Discounts | "how much does drain cleaning cost" $23, 2 clicks, 0 conv |
| costco | Phrase | Costs, Discounts | "water heater replacement costco" $29, 0 conv |
| lowes | Phrase | Costs, Discounts | "lowes plumbing dept" $7, 0 conv |
| plumbing store | Phrase | DIY | "plumbing store seattle" $5; "plumbing dept" $7; 0 conv |
| apollo hydroheat | Phrase | DIY | "apollo hydroheat water heater replacement" $5 (product/brand research), 0 conv |
Services 2 Sons does not lead with. Add to Different Service or Trade as phrase. Confirm each against the current service menu first.
| Term | Match type | Set | Evidence (30d) |
|---|---|---|---|
| irrigation | Phrase | Different Service or Trade | "irrigation plumbing near me" $49, 0 conv |
| well pump / well services | Phrase | Different Service or Trade | "well pump company near me" $10; "well services near me" $2; 0 conv (confirm 2 Sons does not do wells) |
| plomero | Phrase | Different Service or Trade | "plomero hispano" $9 (Spanish-language, no Spanish LP), 0 conv, review |
2 Sons brand searches landing in the non-brand campaign. Not waste (high intent, cheap), but they belong in the brand campaign, which is cheaper and already shows for nearly every brand search. Add to Brand Terms - 2sons so non-brand excludes them and brand catches them. The set is attached to non-brand already (21 members) but these slipped past it, so it needs topping up.
| Term | Match type | Set | Evidence (30d) |
|---|---|---|---|
| 2 sons plumbing & sewer | Phrase | Brand Terms - 2sons | $62, 4 clicks, 0 conv in non-brand |
| 2 sons plumbing tacoma | Phrase | Brand Terms - 2sons | $39, 3 clicks, 0 conv |
| joe's 2 sons plumbing | Phrase | Brand Terms - 2sons | $29, 2 clicks, 0 conv |
| joe's two sons plumbing | Phrase | Brand Terms - 2sons | $3, 0 conv |
| 2 sons plumbing heating & air | Phrase | Brand Terms - 2sons | $13, 0 conv |
| 2 sons plumbing sewer heating & air | Phrase | Brand Terms - 2sons | $10, 0 conv |
| 2 sons and joe's plumbing | Phrase | Brand Terms - 2sons | $2, 0 conv |
| sons plumbing | Phrase | Brand Terms - 2sons | $25 + $2, 0 conv |
No hiring terms surfaced in this window's top terms (a "2sons-SEM-LG-Hiring" campaign exists but is paused). If we turn on hiring or acquisition campaigns later, employment negatives ("jobs," "careers," "hiring," "salary") should be added to the lead-gen campaigns then. Nothing to push today.
Generic in-area plumbing terms that did not convert this window but are legitimate demand: "plumber near me," "plumbers near me," "plumbing in seattle," "plumbing company," "plumbing services near me." These are the core of the non-brand campaign. The fix for their efficiency is Quality Score and bidding, not negatives. We do not exclude them.
The bigger lever behind this list: most of these leaks come through 124 broad-match keywords in the non-brand campaign feeding a Maximize Conversions bid that is chasing a muddy call signal. Negatives treat the symptom; tightening those broad-match keywords toward phrase and exact stops most of this at the source. We recommend both: push these negatives now, tighten match types during the week-2 Quality Score work.
55 campaigns exist. Only 3 are enabled, and only 2 actually spend. One correction to a pre-audit headline: we counted 3 enabled campaigns today, not 4 (the third, the Landing Page Test, spends nothing); the paused PMAX trio brought the "recently active" count higher earlier in the window.
| Campaign | Status | Note |
|---|---|---|
| 2Son-SEM-Brand-Seattle | Enabled | Spending, healthy, over-budgeted |
| 2Sons-SEM-LG-Plumbing (non-brand) | Enabled | Spending, starved and low QS |
| 2Sons-SEM-LG-Plumbing Landing Page Test | Enabled | $0 spend: shares budget ID ...220844 with non-brand, so it can never spend (section 05) |
| 3x PMAX Retargeting | Paused | Paused July 20, $3,012 spent first (section 05) |
| ~48 others | Paused | Three generations of dead structure |
The ~48 paused campaigns are three generations of past-agency structures: manual-CPC relics with $1,000+/day budgets left attached (Water Heater Repair at $1,000/day, Sewer Pipe Lining at $1,500/day), an "H - {city} - {service}" grid (H - Seattle - Plumbing, H - Tacoma - HVAC, and so on), and WS-era 2023 campaigns. None are spending, so they are not urgent, but they make the account hard to read and carry oversized budgets that could be triggered by accident. Cleanup is a later, low-risk tidy.
None of this is a blame point for Natalie. It is the inherited state of the account, and it is fixable.
In order, and the order matters: this follows the Google Ads Success Formula (right traffic, right tracking, right bidding) and the conversion-tracking-first principle. The constraint here is tracking, so we stop and fix that before anything downstream. Non-brand Quality Score is the second constraint, and it gets the landing-page and match-type work once the signal is honest.