Case Studies / SingleOps ROAS Tracking
SingleOps Playwright Zapier Google Ads Microsoft Ads

The API Only Worked One Way. So We Found Another Way Out.

A home services business running ads on Google and Microsoft had no idea what those ads were actually earning. Their job management software — SingleOps — held all the revenue data, but the API turned out to be write-only. Here's how we got the data out anyway, and wired it into both platforms as offline conversions so ROAS was finally visible.

Real ROAS

Visible in Google & Microsoft Ads

0 API calls

Worked around the dead-end API entirely

Automated

Daily revenue pull, no manual exports

The Problem

Ads Were Running. Jobs Were Being Won. Nobody Could Tell Which Ads Were Responsible.

The client ran a home services business — the kind where a lead clicks an ad, books a job, and pays weeks later when the work is done. Google and Microsoft were both running campaigns. Leads were coming in through both platforms. Jobs were being completed and invoiced in SingleOps, their field service management software.

The problem was that the data lived in two places with no connection between them. The ad platforms knew about the click. SingleOps knew about the revenue. Nothing joined the two together. So when anyone asked what the Google Ads campaigns were actually earning — not just how many enquiries they generated, but what those enquiries were ultimately worth in confirmed job revenue — the answer was a shrug.

Without that connection, every media decision was flying blind. Budget allocation between Google and Microsoft, bid strategy choices, campaign-level investment — all of it based on lead volume and cost-per-lead rather than actual revenue return. That's a meaningful difference in a business where job values vary widely and some enquiry sources bring in consistently larger jobs than others.

The goal was straightforward: pull the final invoiced job value out of SingleOps, match it to the click ID that originally brought the lead in, and upload it back to Google and Microsoft as an offline conversion so both platforms could calculate real ROAS.

"The clicks were tracked. The revenue was tracked. The two had never met. Every ROAS figure in the ad platforms was decorative."

The Dead End

There Was an API. It Just Didn't Do What Anyone Thought It Did.

Before we started, the client had already been told by the SingleOps team that an API was available. Our initial research backed that up — the documentation existed, endpoints were listed, it looked like a standard data integration was on the table.

When we dug into it properly, the picture changed. The API was real, but it was designed entirely for pushing data into SingleOps — syncing contacts from a CRM, creating jobs programmatically, that kind of thing. For reading data back out — for the extraction side that we actually needed — there was effectively nothing. The endpoints that existed were not going to give us the invoiced revenue data in any form we could work with.

This is a more common situation than it should be. "We have an API" often means "we have an API for specific inbound integrations we've decided to support," not "you can freely query your own data." SingleOps is not unusual here — many field service management platforms are in the same position. Their integration story is built around getting data in, not getting it out.

If you're evaluating field service software for data portability

Always ask specifically: "Can I query my job revenue data via API with full filtering and date range control?" A generic "yes, we have an API" from a sales team is not an answer to that question. Get it in writing and test it before you build any integration dependency on it.

Our Solution

If the API Won't Give Us the Data, We'll Get It the Way a Human Would — and Automate That Instead

SingleOps did have one thing that worked in our favour: a custom report builder that could produce exactly the revenue data we needed, and that would email the report on demand. The question was how to trigger that automatically, at the right time, with the right date range — without a human doing it manually every day. The answer was Playwright.

Pipeline Architecture

1. Playwright headless browser — scheduled daily

Logs into SingleOps, navigates to Reports, sets the correct date range, triggers the custom revenue report

2. SingleOps emails the report

CSV attachment lands in the designated inbox within minutes of the trigger

3. Zapier picks up the email

Triggered by the specific sender and subject pattern; extracts the CSV attachment

4. Data cleaning & enrichment

Zapier formatter + code step: strips formatting, normalises currency, joins Google Click ID and Microsoft Click ID columns, validates rows

5a. Google Ads upload

Offline conversion import via Google Ads API — GCLID + revenue value

5b. Microsoft Ads upload

Offline conversion import — MSCLKID + revenue value

1

Playwright Headless Browser — The Engine Room

Playwright is a browser automation framework that can drive a real browser — logging in, clicking, filling forms, navigating — without a screen. We wrote a script that ran on a schedule, opened SingleOps in a headless Chromium instance, authenticated with the client's credentials, navigated to the custom reports section, set the date range to the previous day's jobs, and clicked to generate and email the report.

From SingleOps's perspective, this was indistinguishable from a human running their end-of-day report. From the client's perspective, it was something that just happened automatically every morning without anyone touching it.

2

Zapier Picks Up the Report and Cleans the Data

SingleOps sends the report as a CSV email attachment. A Zapier zap watched the inbox for emails matching the SingleOps report sender and subject pattern, extracted the attachment, and began processing it. The raw export needed cleaning — currency symbols, inconsistent field names, rows representing partial jobs, duplicate entries — all of which were handled in Zapier's formatter and code steps before the data moved anywhere.

The click IDs — Google's GCLID and Microsoft's MSCLKID — had been captured at the lead enquiry stage and stored against each job record in SingleOps. The cleaning step matched those IDs to the correct revenue rows, producing a clean upload-ready file for each platform.

3

Offline Conversion Upload to Google and Microsoft

The cleaned data was uploaded to Google Ads as offline conversions — each row containing a GCLID, the conversion timestamp, the conversion action name, and the invoiced job value. The same process ran in parallel for Microsoft Ads using the MSCLKID equivalent.

Both platforms then had access to the actual revenue outcome for every click that had converted into a completed job. Bidding algorithms on both sides could now optimise toward real revenue rather than lead volume. ROAS was finally a real number.

The Result

Real ROAS. Real Bidding Signals. Decisions Based on Revenue, Not Leads.

Once the pipeline was live and the first conversion uploads had processed, both ad platforms had what they needed. ROAS figures appeared in Google and Microsoft Ads dashboards that were based on actual invoiced job revenue, not on lead count or estimated values. For the first time, the client could see which campaigns, which ad groups, and which keywords were generating work worth taking — and which were producing enquiries that went nowhere or that weren't worth their acquisition cost.

The smart bidding algorithms on both platforms were able to use the revenue signal almost immediately. Campaigns that had been optimising toward lead form submissions shifted to optimising toward confirmed job revenue. That shift alone changed how budget was allocated across campaigns and how aggressively certain high-value keyword segments were bid on.

The other consequence was that budget decisions between Google and Microsoft became data-driven for the first time. Previously, spend was split based on gut feel and rough lead count. With revenue data flowing into both platforms, the comparison became straightforward: which platform was generating better returns on the same spend?

Both Platforms

Google Ads + Microsoft Ads receiving revenue data simultaneously

Daily

Revenue data automatically refreshed each morning without manual intervention

Zero Changes

To SingleOps or existing workflows — solution worked around the platform, not through it

Running Ads Against a Platform That Won't Give You Its Data?

If your job management or CRM software is sitting between your ad spend and your revenue data, there's usually a way to bridge that gap — API or not. Get in touch with a brief of your setup and where the data currently lives.

Brendan Andrew Chase

Written by

Brendan Andrew Chase

Conversion tracking specialist and marketing automation consultant with 10+ years connecting ad platforms to real revenue data for service businesses across the US, UK, and EU. 200+ projects delivered. Founder of Extra Large Marketing Digital, based in Rio de Janeiro.