Littledata MonitorAI guide

Google Ads conversion connection v2 (web action) — detection and predicted uplift

Investigation date: 2026-08-24 Trigger: Littledata launched a second Google Ads purchase connection as a parallel option. It is a real web conversion action rather than an offline click upload, and it is expected to have more attributed revenue than the v1 upload. This document records what the v2 action looks like in the data, what it actually reports against v1 in the accounts running both, and how the value model reads it.

Background on why v1 was capped in the first place: UPLOAD_CLICKS conversion actions do not receive view-through attribution.

Update 2026-08-28 — the view-through mechanism is a minority contributor, not the main one. Littledata Google Ads purchase connection: v1 vs v2, measured measures where the uplift actually comes from across all five accounts running both connections. Impression-side credit (ENGAGED_VIEW + IMPRESSION) accounts for 0% to 31% of the v1→v2 difference — 31% on becausemarket-prod, 0% on soda-sense — with click-side match-rate and value gains the larger half wherever there is a gain at all. Read the split from segments.conversion_attribution_event_type, never from metrics.view_through_conversions, which omits engaged views and understated becausemarket-prod’s impression-side uplift 11-fold.


Telling the two connections apart

Both connections use the same action names, so type is the only reliable discriminator — never the name.

  v1 v2
conversion_action.type UPLOAD_CLICKS WEBPAGE
Google Ads UI “Conversion source” Website (Import from clicks) Website
Action name Purchase - Littledata, or Purchase - Littledata (<customerId>) Purchase - Littledata (Web)
Click-through window 90 days 90 days
View-through window 1 day (and structurally inert — see linked doc) 30 days
Attribution owner Littledata, keyed on the original click ID Google

Naming is consistent across every account with v2: only the three Purchase / New Customer Purchase / Returning Customer Purchase families, each suffixed (Web). ldPurchaseConnectionVersion() in src/services/googleAds/constants.ts is the single place that decides which connection an action belongs to.

The two connections attribute the same orders. Nothing may ever sum them.


Accounts running v2 (as of 2026-08-24)

Six accounts had a v2 web purchase action in the last 40 days of snapshots: soda-sense, tentbox-6623, becausemarket-prod, jimmy-joy, gardeners-dream-online, sparklingjewels-com. All three named in the launch brief are confirmed present, with the v2 action captured in the daily conversion snapshots (byAction.actionType = "WEBPAGE", category PURCHASE).

Every rollout follows the same shape: v2 appears at a trickle, climbs over roughly two to three weeks, then plateaus near v1. Crossover happened around 2026-08-10 to 2026-08-13 for the three earliest accounts.

What v2 actually reports against v1

Steady-state comparison — settled days only, ramp-up excluded (see computeGoogleAdsV2UpliftBenchmark):

Account Steady days v2 ÷ v1 attributed revenue
becausemarket-prod 11 1.23×
soda-sense 10 1.10×
tentbox-6623 7 0.95×
jimmy-joy 8 0.83×

Cohort median 1.03×, P25 0.92×, P75 1.13×.

This measurement is not yet usable, and it does not set the customer-facing figure. tentbox-6623 and jimmy-joy had only just started when this was measured, so their sub-parity readings describe an unfinished rollout rather than the connection — which is most of what drags the median to 1.03×. The single-week comparisons in the launch screenshots (Soda Sense 1.15×, Because Market 1.17×) come from the two accounts that had finished.

Two more accounts are excluded as not yet measurable at all: gardeners-dream-online (v2 switched on 2026-08-23, one partial day) and sparklingjewels-com (v2 only, no v1 to compare against).

Revisit from 2026-09-07, by which point the four current donors will have a fortnight of settled steady-state history and gardeners-dream-online should qualify. Until then the value model quotes a flat assumption (below).


How the value model reads it

The comparison point (googleAdsRoasFromSnapshots)

Each candidate ROAS window sums the two connections separately and reads whichever reported more over that window, recording the choice as ldPurchaseVersion alongside both raw totals.

Preferring the larger rather than always preferring v2 is deliberate: a v2 connection switched on mid-window is still filling in, and reading the partial side would compare a fortnight of Littledata against a full quarter of baseline. The consequence while v2 is young is that short windows (7/14-day) already read v2 in soda-sense, becausemarket-prod and sparklingjewels-com, while long windows still read v1 — two weeks of v2 cannot out-total 90 days of v1. It resolves itself as v2 accumulates history.

An account running only v2 (v1 switched off) now registers as Littledata-active at all; before this change it produced no Google Ads value tier.

Not double-counting the view-through correction

googleAdsAttributionWindowValueUpliftFactor exists to credit v1 for what widening its lookback windows would add. v2 already carries both the account’s normal 30-day view-through window and a 90-day click window — the window the experiment widens v1 to — so the factor is applied only when the comparison reads v1, per aggregation and per window score. (Since the 2026-05-23 resolution the experiment holds view-through fixed and widens click windows only, so the click window is the part of that sentence doing the work.)

Assumed uplift for accounts still on v1

For an account with no v2 activity at all, the model estimates what v2 would add using GOOGLE_ADS_V2_ASSUMED_UPLIFTa flat 10% launch assumption, not the measured median:

predicted additional revenue = own v1 revenue × 1.10 − Littledata value already reported

Subtracting the reported value (not raw v1) is what stops an account whose v1 lookback windows were already widened by a conversion-window experiment from being credited twice for attribution it already won — v2’s own wider windows are the same mechanism.

Gates, all of which must pass before anything is stored or shown:

It surfaces as one line on the Google Ads hero card:

Test out Littledata’s Google Ads v2 connection to capture another 10% more attributed revenue

The percentage is interpolated from the constant, so changing the assumption changes the copy. The line quotes no dollar figure on purpose: putting a precise monthly amount on an assumed rate would dress the assumption up as a measurement. The dollar estimate is still stored on the tier (googleAdsV2PredictedAdditionalRevenueUsd) for internal sorting, and is never part of value, any ROI, or any value total — it is a counterfactual about a connection the account does not run.

Audit checks

checkGoogleAdsGoalConfig counts a Littledata-named WEBPAGE purchase action as Littledata being configured and primary, so an account that finishes migrating to v2 is not told Littledata is missing. A v1 action losing primary while a v2 action holds the goal is the migration completing, not a demoted goal, and no longer raises a warning — narrowed to v1 actions and only when a v2 action is actually primary, so v1-only accounts behave exactly as before.

Baseline selection was already safe: every Littledata-named action is excluded from baseline candidates by name, so the v2 action could never have been picked as a competing pixel.


Watching the ratio

npx tsx scripts/report-google-ads-v2-uplift.ts

Prints the assumed uplift, the measured cohort median against it, and the per-donor breakdown. Pass --refresh to bypass the one-day cache. At the 2026-09-07 revisit, if the donor set has reached V2_UPLIFT_MIN_SAMPLE_SIZE with settled history, replace GOOGLE_ADS_V2_ASSUMED_UPLIFT with the measured ratioP50 - 1 — the script prints the exact value to use.

Files