You spend $4,000 on Meta Ads in a month. Meta says you got 14,000 link clicks and 312 conversions. DoorDash says you did $32,000 in revenue that month. You have no idea how much of that revenue came from those clicks.
This is the standard restaurant marketing situation. It is fixable, but to fix it you have to understand exactly where the signal is dropping. The good news is: the chain is mechanical, every step is named, and you can audit your own setup in about ten minutes.
Here is what the chain actually looks like.
Step 1: A click happens on Meta
Someone scrolls Instagram. They see your ad. They tap it.
Meta attaches a URL parameter called fbclid to the outbound link. That parameter is the identity token for this specific click. It looks like this:
https://your-restaurant.com/order?fbclid=IwAR3xH7-4K_QwR2BvN8...
The fbclid value is a unique, opaque string. Meta keeps a record of it on their side. As long as Meta can later observe a server-side conversion event that includes this same fbclid, they can match the click to the conversion.
So far so good. The user is now leaving Meta with an identifier in their URL.
Step 2: The browser lands on a destination
The browser hits whatever URL was inside that ad. For most restaurants, this is one of three setups:
Setup A — direct to DoorDash. The ad URL is something like https://www.doordash.com/store/your-restaurant-12345/. The browser opens DoorDash. The fbclid parameter is in the URL when DoorDash’s page first loads. DoorDash does not read it, does not store it, does not send it back to Meta. The signal is dead.
Setup B — through a Linktree-style aggregator. The ad URL is something like https://linktr.ee/your-restaurant. The aggregator page loads with fbclid in the URL. The aggregator does not fire a Meta CAPI event. The user picks DoorDash. The browser navigates to DoorDash, but the fbclid is gone — it was on the Linktree URL, not the DoorDash one. Signal dead.
Setup C — through a smart-link page you control. The ad URL is https://yourbrand.com/order?fbclid=.... Your page loads. Before the user picks a platform, your page fires a server-side event to Meta containing the fbclid. Now Meta has confirmation: “yes, this click landed and was real.” This event is the Landing Page View. When the user picks DoorDash and clicks through, you fire a second event: the platform_click. This carries the fbclid plus a fresh event_id.
Setups A and B are why restaurant marketers complain about attribution. Setup C is what server-side tracking unlocks.
Step 3: The Meta Pixel and Conversions API
Meta runs two parallel tracking systems. Both can carry the fbclid. Both can fire on a smart-link page.
The Pixel is the client-side JavaScript snippet that runs in the diner’s browser. When the page loads, the Pixel sees the URL parameters, sets a first-party cookie called _fbc to capture the fbclid value (and another, _fbp, to identify the browser session), and fires a PageView event. The Pixel works well, but it is increasingly blocked by Safari ITP, iOS 14.5+ ATT prompts, and ad blockers. Coverage is typically 50-70% on mobile restaurant audiences.
The Conversions API (CAPI) is the server-side version. Your server makes an authenticated HTTPS call to graph.facebook.com/v18.0/{pixel_id}/events with the event payload. CAPI runs even when the browser blocks the Pixel. It covers the 30-50% of users the Pixel misses.
The trick is dedup. If you fire the same event from both the Pixel and CAPI, Meta needs to know they are the same event so they don’t double-count it. You accomplish this by passing the same event_id from both sides — usually a UUID generated when the page loaded, stored in a cookie, and passed to both the Pixel call and the CAPI call.
Step 4: What CAPI sends
A well-formed CAPI event for a restaurant platform_click looks something like this:
POST https://graph.facebook.com/v18.0/447382372097589/events
{
"data": [{
"event_name": "platform_click",
"event_time": 1715275200,
"event_id": "e7b3c8f0-1a2d-4e5f-8a9b-c1d2e3f4a5b6",
"action_source": "website",
"event_source_url": "https://yourbrand.com/order",
"user_data": {
"client_ip_address": "172.58.x.x",
"client_user_agent": "Mozilla/5.0 (iPhone...)",
"fbc": "fb.1.1715275000.IwAR3xH7-4K_QwR2BvN8...",
"fbp": "fb.1.1715274900.1234567890"
},
"custom_data": {
"platform": "doordash",
"location_id": "southlake"
}
}]
}
The fbc field is the fbclid reformatted into Meta’s canonical “click ID” format: fb.{subdomain_index}.{timestamp_ms}.{fbclid_value}. The fbp is the browser cookie. Together with IP and user agent, this gives Meta enough information to match this event back to the original click — even if the user is on Safari with the Pixel blocked, even if they took 45 minutes to make a decision, and even if they never gave you their email.
Step 5: Meta matches the click to the event
Meta’s matching algorithm runs in the background. It looks at every server-side event you send, checks the fbc/fbp/IP/UA combination against its own records of recent ad impressions and clicks, and assigns a Match Quality score from 0 to 10.
- 0-3: Meta cannot confidently match this event to a click. Useless for optimization.
- 4-6: Some matches. Optimizer may use the data with low confidence.
- 7-9: Strong matches. The optimizer treats these events as real conversions and builds its audience model around them.
- 10: Perfect match. Rarely achievable without authenticated user data (email or phone).
Restaurant smart-link platform_click events using only IP/UA/FBC/FBP typically land at 7-8. Adding hashed email or phone (if you have them from a loyalty program or POS integration) pushes it to 9. The jump from 4 to 7 is where the optimizer’s behavior changes meaningfully.
Step 6: The order happens on DoorDash
This is the part you cannot see. The user clicks “Order on DoorDash” on your smart-link page, fires the platform_click event, and is redirected to DoorDash with ?utm_source=meta&utm_medium=cpc&utm_campaign=your-campaign-name. They place an order. Money moves. Neither DoorDash nor Meta tells you which fbclid that order came from.
You can close part of this loop with UTM-based reporting from DoorDash’s merchant portal (they will show you “channel: meta” revenue if you set the UTM cleanly). You cannot match a specific order back to a specific click. Nobody can, including DoorDash. That is the structural limit of the chain.
Where the signal usually drops
Restaurant attribution leaks at four well-known points. Audit each one on your own setup.
- No fbclid in the destination URL. Some agencies set static destinations and lose the parameter. Verify by clicking your own ad in incognito and watching the URL bar.
- Destination is the ordering platform directly. No page exists between the ad and DoorDash where you can fire CAPI. Add a smart-link.
- Pixel fires but CAPI does not. Browser blocking eats 30-50% of events. Verify in Meta Events Manager’s “Server” tab.
- Events fire but Match Quality is 2-4. Missing IP, missing UA, missing fbc, or fbc not formatted correctly. Inspect a recent event payload.
Each one is fixable in a day. None of them require migrating your ordering stack.
If you want a working reference, every Malai Kitchen smart-link page on DineRoute fires both Pixel and CAPI with deduplicated event_ids, IP, UA, FBC, FBP, and a custom platform_click event. You can audit one live at malai.dineroute.com/southlake — open dev tools, watch the network panel, and you will see the event fire on every platform tap.
Related reading: