Time · marketers · PMs · engineers
Last click is a story. Data-driven is a model.
The tag sent one Purchase; three reports claimed it. Paid search last-click, GA4 data-driven, and Meta's own model each used a different set of touches and a different window.
Last-click
The last click inside the window gets 100% of the conversion. Easy to explain. Blind to the prospecting ad that created the search. Direct and branded paid search harvest last-click by construction. If that is the scoreboard you chose, prospecting will look expensive and brand will look like a miracle.
UTM last-click in GA4 is this story told with utm_source, not with gclid. A redirect that kept UTM and dropped gclid will look attributed in GA4 and unattributed in Google Ads. Keep both parameters. Last-click on UTMs is also blind to view-through, because UTMs are not impressions.
Data-driven
Google Ads and GA4 data-driven attribution assign fractional credit from observed converting and non-converting paths. You cannot reproduce the weights in a spreadsheet. You can change the conversion the model trains on, and you can starve it by sending bad event times or duplicate Purchases.
Meta's optimization is also a model on events it can match. Event Match Quality and honest event_time matter more here than a last-click rule you set in a dashboard the bidder does not read. A 13-digit event_time never enters the model. A missing gclid on Ads never enters the click path the model wants.
Do not mix the scoreboards
A last-click ROAS target on a data-driven campaign, or a GA4 last-click export used to bid in Ads, is two models fighting. Pick one credit model per decision. Document which UI is source of truth for spend, and which warehouse table is source of truth for finance.
Windows still apply. Data-driven will not credit a click outside the conversion window. Fixing attribution model will not fix a 13-digit event_time or a missing gclid. Contracts first, models second. View-through on or off is yet another axis. Last-click plus view-through is a contradiction in the brief even if the UI allows a messy export.
Time still has to be right
Models sit on events. Events sit on clocks. Meta needs 10-digit seconds. GA4 MP needs 16-digit microseconds if you send timestamp_micros. Amplitude and LinkedIn need 13-digit milliseconds. PostHog and Segment need ISO 8601. A wrong unit is not a modeling disagreement. It is a dropped or mis-dated hit. The weekly 'Ads and GA4 do not match' meeting should check units before models.
Pixellint validate json on the conversion body is the contract check. It will not pick last-click vs data-driven for you. Pixellint is not affiliated with Google or Meta.
What engineering still owns
gclid, fbclid, ttclid, msclkid, li_fat_id, twclid captured and replayed. Hashed email and phone. IP and UA in the clear. event_id shared across pixel and CAPI. event_time in the vendor's unit, the time of the action. Without those, every model is ranking noise.
PMs own which UI is the decision scoreboard. Engineers own whether the hit could enter that UI at all. A data-driven report cannot rescue a Purchase whose event_time was Date.now() milliseconds on Meta.
// Models do not read this
custom_data: { model: 'data-driven' }
// What they actually train on: a legal, dated, identified conversion
event_name: 'Purchase',
event_time: Math.floor(purchasedAtMs / 1000), // Meta: 10 digits
event_id: orderId,
user_data: {
em: sha256hex(email.trim().toLowerCase()),
fbc: cookies._fbc,
client_ip_address: shopperIp, // not hashed
}
Check the artifact
Paste the pixel URL or JSON body into the
playground. Same engine as
pixellint validate. Nothing leaves the tab.