Offline & CRM events
Send POS, CRM and call-center conversions server-side, tagged with the right action source.
Not every conversion happens in a browser. A cash sale at a counter, a deal closed on a phone call, an order entered by a call-center agent, a subscription renewed by a back-office job: none of these fire a pixel, but they are still conversions your ad platforms should learn from. PixelFox accepts them through the same ingest API, tagged so Meta records them correctly.
What makes an event "offline"
Two things:
-
There is no browser cookie, so matching relies entirely on the customer's hashed email and phone. Always send whichever you have.
-
The
action_sourcetells Meta where it happened. PixelFox forwards it to the Conversions API verbatim (browser events default towebsite):action_sourceUse for physical_storeIn-store POS sales phone_callOrders taken over the phone chatWhatsApp / Messenger / live-chat sales emailDeals closed over email system_generatedBack-office jobs (renewals, reconciliations)
Python
from pixelfox import PixelFox
signals = PixelFox(api_key="sig_live_...")
signals.offline(
event="purchase",
value=2400,
currency="BDT",
order_id="POS-5591",
phone="+8801712345678", # hashed server-side, never stored raw
email="[email protected]",
action_source="physical_store",
)PHP / Laravel
use PixelFox\Facades\PixelFox;
// track(string $event, array $properties = [], ?string $distinctId = null)
PixelFox::track('purchase', [
'value' => 2400,
'currency' => 'BDT',
'order_id' => 'POS-5591',
'phone' => '+8801712345678',
'email' => 'maya@example.com',
'first_name' => 'Maya',
'last_name' => 'Rahman',
'city' => 'Dhaka',
'country' => 'BD',
'$action_source' => 'physical_store',
], 'pos-terminal-3');
// Or the purchase helper, with the shopper's own IP and user agent from the
// checkout request so Meta matches the browser session, not your server:
PixelFox::purchase('1001', 129.5, 'BDT', $order->email, [], [
'first_name' => $order->first_name,
'last_name' => $order->last_name,
'phone' => $order->phone,
'city' => $order->city,
'zip' => $order->postcode,
'country' => 'BD',
'external_id'=> (string) $order->user_id,
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
], $request->cookie('signals_did'));Server-side events carry your server's IP unless you pass the shopper's as
client_ip_address (and client_user_agent); the helpers above do that for you.
Raw HTTP
Any language can post to the ingest API directly. $action_source is just an event
property:
curl -X POST https://api.pixelfox.app/v1/ingest \
-H "X-Signals-Key: sig_live_..." \
-H "Content-Type: application/json" \
-d '{
"events": [{
"event": "purchase",
"distinct_id": "callcenter-agent-7",
"properties": {
"value": 2400, "currency": "BDT", "order_id": "CALL-118",
"phone": "+8801712345678", "$action_source": "phone_call"
}
}]
}'Notes
- Send within 7 days. Meta's attribution window means an offline conversion reported much later matches poorly. Report POS and call sales daily, not monthly.
- Reuse the browser distinct id when you have it. If the customer browsed your site
first (from the
signals_didcookie), pass it asdistinct_idso the offline sale joins the same journey and identity stitching connects it to their online behavior. - Offline events flow to every configured destination, count in your dashboard and
funnels, and dedupe by
event_idlike any other event.