01 Insights
How to set up call tracking for a service business
Written for a different reader. This was published under the previous positioning, for local service businesses. The engineering in it is unchanged and still correct; the audience it addresses is not the one this studio now sells to.
A practical guide to call tracking for service businesses: choose methods, set up dynamic number insertion, and nail attribution.
You can’t track ROI if you don’t know which calls came from where
You’re paying for ads, you’ve tuned your Google Business Profile, and the phone rings, but which channel drove the call? If you’re guessing based on gut, here’s a clean way to measure it end to end without ripping out your site.
The two call-tracking methods that actually matter
You’ll use one or both of these:
- Website pools with dynamic number insertion (DNI). A pool assigns a unique tracking number to each visitor session and swaps it into your site via JavaScript, so the platform can tie the inbound call back to that visitor’s source/UTM/keyword. See the overview from CallRail Support.
- Dedicated forwarding numbers used directly in ads and listings (no swapping). You place a tracking number in a Google Ads extension, a Facebook campaign, or a directory profile. Calls to that number attribute to that placement. This approach is covered in the website pool documentation from CallRail Support, which explains using website pools alongside forwarding numbers (including Google’s own forwarding for “calls from ads”).
Most service businesses combine both: a website pool for all site traffic and dedicated numbers for ad extensions and major directory listings.
How big should your tracking number pool be?
Under-provisioning wrecks attribution on busy days. Keyword-level pools have a documented minimum of four numbers per pool in the CallRail PDF guide. Providers reuse numbers after a session ends, but if all numbers are in use (pool exhaustion), new visitors may get a reused number and you’ll see misattribution.
- For low-traffic local sites, start at the documented minimum and watch for exhaustion flags in your call-tracking dashboard.
- If you’re building in-house with a telephony platform and want full control, the “Proxy” model from Twilio Docs shows how to assign, track, and reuse numbers programmatically to prevent collisions.
Implement dynamic number insertion (DNI) on your site without breaking UX
Here’s the reliable, vendor-agnostic checklist. The steps align with visitor tracking basics from CallRail Support.
- Create a website (or keyword) pool
- Choose local numbers that match your service area or toll‑free if you serve multiple states.
- If you run Google Ads with keywords you care about, configure a keyword pool (minimum four numbers per the CallRail PDF guide).
- Install the swap script across the whole site
- Add the provider’s JavaScript snippet to your global layout so it loads on every page and subdomain where your phone number appears. You can also add it via Google Tag Manager if that’s how your stack is set up. The DNI script (often named swap.js or similar) scans for your existing numbers and replaces them in the DOM, as described by CallRail Support.
- Make your numbers detectable
- Use tel: links and plain text for visible phone numbers. Avoid baking numbers into images/SVGs. Non-standard formats can prevent detection and swapping, a common cause of untracked calls.
- If you have vanity formats, annotate them with a wrapper class or data attribute so the script can target them.
- Test the swap and persistence
- Open a private window, land on a page via a UTM-tagged URL, and confirm the phone number swaps.
- Click into another page and check that the same tracking number persists.
- Test on mobile and any subdomain (e.g., booking.yoursite.com). Missing the script on a subdomain leads to number flips mid-session and lost attribution.
- Verify attribution flows
- Place a test call from the swapped number and look for session details (source, medium, campaign, keyword if available) in your call-tracking dashboard, per the behavior described in CallRail Support.
Optional: a resilient CSS selector strategy If your site has multiple phone placements (header, hero, sticky footer, contact page), give them a shared class like .trackable-phone and configure your provider to target that selector.
Example HTML:
<a class="trackable-phone" href="tel:+12035551234">(203) 555‑1234</a> <span class="trackable-phone">(203) 555‑1234</span>
<a class="trackable-phone" href="tel:+12035551234">(203) 555‑1234</a> <span class="trackable-phone">(203) 555‑1234</span>
This avoids relying on fragile regex-only swaps and keeps the display consistent.
Use forwarding numbers in ads and directories (without fighting your website pool)
- Google Ads call extensions and “call-only” ads: Assign a dedicated tracking number for the extension or use Google’s own forwarding for calls from ads, as covered in CallRail Support. Keep this separate from your website pool; the call never hits your site.
- Major directories (Yelp, Angi, Healthgrades): Place unique forwarding numbers per high-value listing so you can see which listing drives inbound.
- Direct mail, yard signs, trucks: If you accept calls directly from offline sources, give each a distinct number too.
Avoid this pitfall: expecting Google Ads auto-forwarding and a third-party DNI script to coordinate without an explicit integration. Use your provider’s Google Ads connector so conversions sync directly into Ads/GA4; the integration paths are documented in the CallRail API docs.
How to attribute calls to ads or organic channels (and make the data useful)
Here’s what your platform will do and how to wire it into your reporting stack.
- Session-based attribution. A visitor lands on the site; the DNI pool assigns a number and stores referrer, UTM parameters, and landing page. When the call comes in, the platform maps it to that session and reports source/medium/campaign (and keyword for eligible paid clicks). See flow details in CallRail Support.
- Keyword-level attribution for Google Ads. With keyword pools, the platform can report the keyword that triggered the ad, per the same CallRail Support article and the minimum pool sizing in the CallRail PDF guide.
- Multi-touch and downstream reporting. Push call events to GA4, sync conversions to Google Ads, and send call metadata to your CRM via webhooks or API so you can connect calls to deals and LTV. Integration routes are described in the CallRail API docs.
Implementation moves that prevent messy data:
- Define a conversion threshold. Count only calls over a set duration or with a specific outcome as conversions. Short hang-ups will inflate “success.” Your call-tracking platform lets you configure this before you send conversions to Ads/GA4.
- Normalize caller ID and session IDs in your CRM. When you push call webhooks, store the provider’s call/session IDs so you can de-duplicate and tie repeat callers to the original source.
Concrete setup examples
Two common setups: a trade contractor and a dental/medical practice. The wiring is similar; the details differ.
Example A: HVAC contractor in one metro
- Channels: Google Ads Search, Local Services Ads (LSA), Google Business Profile, one or two big directories, and some seasonal mailers.
- Tracking numbers: Website keyword pool (minimum four numbers per the CallRail PDF guide) to capture source/keyword for paid and organic sessions. One dedicated number for Google Ads call extensions or use Google’s forwarding for “calls from ads” per CallRail Support. One number for the top directory (e.g., Yelp) and one for mailers.
- Website keyword pool (minimum four numbers per the CallRail PDF guide) to capture source/keyword for paid and organic sessions.
- One dedicated number for Google Ads call extensions or use Google’s forwarding for “calls from ads” per CallRail Support.
- One number for the top directory (e.g., Yelp) and one for mailers.
- Site implementation: Add the DNI script to your main domain and any subdomains hosting quote forms. Mark all visible numbers with a .trackable-phone class.
- Reporting: Push qualified calls to GA4 and Google Ads via the integration flows in the CallRail API docs. In GA4, build a custom report filtered by Event Name = phone_call and break down by Source/Medium. In Ads, import the conversion action created by the connector.
- QA checklist: UTM-tag all non-organic campaigns; test a call from each pathway; confirm LSA calls are reported in the LSA dashboard separately from your third-party tracking.
Example B: Dental or medical practice with two locations
- Channels: Organic search, Google Ads for “dentist near me” plus services (implants, Invisalign, urgent care), location pages, and healthcare directories.
- Tracking numbers: One website pool per location to avoid cross-location collisions and keep reporting clean. Dedicated numbers for the most important ad extensions per location. A unique number on each major directory profile per location to understand which listings produce booked appointments.
- One website pool per location to avoid cross-location collisions and keep reporting clean.
- Dedicated numbers for the most important ad extensions per location.
- A unique number on each major directory profile per location to understand which listings produce booked appointments.
- Site implementation: Each location page uses a location-specific, human-readable office number in the HTML that the script swaps from the correct pool. Ensure the header/footer don’t hardcode a single office number; use a data attribute the script can target.
- Routing sanity: Route each location’s tracking numbers to that office’s front desk without changing your IVR options.
- Reporting: Push call events into GA4 with a location parameter. In the CRM/EHR integration, map calls to the correct office and appointment type. Use the CallRail API docs to pass call metadata, then build location-level performance views.
Common mistakes that break attribution (and how to avoid them)
- Too few numbers in the pool. This causes pool exhaustion and bad mappings. Follow the minimum for keyword pools from the CallRail PDF guide and scale up if you see warnings.
- Script not installed on all pages/subdomains. If the header shows your real number but the contact page swaps to a tracking number, the call might not tie back to the original session. Install once globally, as emphasized in CallRail Support.
- Numbers inside images/SVGs or fancy markup the script can’t find. Keep phone numbers as text and tel: links; if you need visuals, wrap the text with accessible styling.
- Assuming Google’s forwarding and third‑party DNI will coordinate attribution automatically. Use the provider’s native Google Ads/GA4 connectors described in the CallRail API docs.
- Counting every ring as a win. Set a minimum call duration or require a positive call outcome before marking a conversion.
What call tracking method should you use?
- If most leads come through the site: start with a website pool + DNI. It ties calls to PPC, organic, and referral traffic.
- If you spend on ads and directories: add dedicated forwarding numbers per placement so you can measure those channels that never touch your site.
- If you need custom routing or own-the-stack control: a programmatic pool using the pattern from Twilio Docs can sit behind your IVR and CRM, but only build this if off‑the‑shelf pools don’t meet a clear requirement.
How to push call data into your analytics and CRM
- Connect Google Ads and GA4 through your call-tracking platform so phone calls appear as conversions. The integration pathways and event payloads are covered in the CallRail API docs.
- In GA4: receive phone call events, apply your conversion threshold, and report by source/medium/campaign.
- In your CRM: receive webhooks for call start/end, duration, recording URL (if you use recordings), and session attribution. Store the provider’s call ID to merge with form submissions from the same user.
Want a partner to wire this into a site that actually converts?
Your implementation checklist
- Inventory every place your phone number appears: site header/footer, hero sections, contact pages, landing pages, subdomains, ads, directories, print.
- Choose your approach: website pool + DNI; dedicated numbers for ads/listings; or both.
- Create pools and dedicated numbers; install the DNI script globally.
- Make numbers detectable (text + tel:). Avoid images/SVG-only display.
- Integrate with GA4, Google Ads, and your CRM via the provider’s connectors or API.
- Set conversion rules (e.g., minimum call duration) and test each pathway end to end.
Take 15 minutes to line up your inventory and choose your tracking approach.
Common questions
What call tracking method should I use for a local service business?
Use a website pool with dynamic number insertion to attribute calls from site traffic, and add dedicated forwarding numbers for ads and major directory listings. This mirrors the approaches documented by CallRail Support for website pools, DNI, and calls from ads.
How many tracking numbers do I need in a pool?
Keyword pools require a minimum of four numbers per the CallRail PDF guide. Start there and increase if your dashboard warns about pool exhaustion during peak traffic.
Will dynamic number insertion affect my SEO or confuse repeat visitors?
DNI swaps the visible number on-page but routes to your business as usual. Install the script sitewide so the same tracking number persists during a session; this avoids confusion and preserves attribution.
How do I get call conversions into Google Ads and GA4?
Use your call-tracking platform’s native integrations to push call events and conversions to GA4 and Google Ads as described in the CallRail API docs, then apply your conversion rules (e.g., minimum duration).