PixelFox Docs
Installation

Python

Server-side conversion tracking for Django, Flask, FastAPI or a worker.

Send conversions from your own back end. A browser event can be blocked and the customer may never load the confirmation page - the order row in your database always exists, so sending from there is what makes a conversion reliable.

Install

pip install pixelfox-sdk

No dependencies: a tracking SDK should not force a version of requests onto your project. Python 3.8 or newer.

Create a client

import os
from pixelfox import PixelFox

pixelfox = PixelFox(api_key=os.environ["PIXELFOX_API_KEY"])
ArgumentDefaultPurpose
api_keyrequiredYour site's key from the dashboard
hosthttps://api.pixelfox.appWhere events are sent. Set it to your custom ingest endpoint, e.g. https://t.yourstore.com
timeout3.0Seconds to wait before giving up on a request
batchFalseBuffer events and send them in one request on flush() or on leaving a with block
on_errorNoneA callable given the error message whenever a send fails
originNoneYour site's origin, e.g. https://shop.example. Needed only when the site restricts allowed origins in Settings

Send a purchase

pixelfox.purchase(
    order_id="1042",
    value=1200,
    currency="BDT",
    # From the `pixelfox_did` cookie, so this joins the same journey as the page
    # views that led to it. Without it the sale looks like a new stranger.
    distinct_id=request.COOKIES.get("pixelfox_did"),
    email=order.email,
    phone=order.phone,
    items=[{"product_id": "p1", "name": "Merino Crew", "quantity": 2, "price": 600}],
    customer={"first_name": "Asha", "city": "Dhaka", "country": "BD"},
    client_ip=request.META.get("REMOTE_ADDR"),
    client_user_agent=request.META.get("HTTP_USER_AGENT"),
)

email and phone are what raise match quality on Meta and TikTok. They are hashed server-side before reaching any ad platform and never reach a browser. customer carries the remaining match keys: first_name, last_name, city, state, zip, country and external_id (your own customer id). client_ip and client_user_agent are the shopper's, from the checkout request, not your server's.

If the browser pixel already fired this purchase, pass its event id as uuid_ so the two are counted once.

Identify a visitor

Their earlier anonymous events are re-attributed to them server-side, so calling this after a signup backfills the whole session.

pixelfox.identify(distinct_id=did, email=user.email, phone=user.phone)

Events that did not happen in a browser

POS sales, CRM updates and call-centre conversions have no cookie to join. email and phone are the whole match here.

pixelfox.offline(
    "purchase",
    value=2500,
    currency="BDT",
    order_id="POS-7781",
    phone="+8801712345678",
    action_source="physical_store",
)

action_source is passed through to the ad platforms; see offline and CRM events for the accepted values.

Batching

For a worker sending many events, buffer and flush once:

with PixelFox(api_key=KEY, batch=True) as pixelfox:
    for order in backfill:
        pixelfox.purchase(order_id=order.id, value=order.total, currency="BDT")
# flushed on exit

Batches larger than 50 are split automatically - the ingest endpoint rejects anything bigger. Without batch=True every call sends immediately.

Errors

Nothing raises into your request path. Analytics failing must not fail a checkout.

pixelfox = PixelFox(
    api_key=KEY,
    on_error=lambda msg: logger.warning("pixelfox: %s", msg),
)

result = pixelfox.track("lead_submitted", distinct_id=did)
if not result.ok:
    logger.warning(result.error)

Every method returns a SendResult with ok, accepted (how many events the server took) and error.

Reference

MethodPurpose
track(event, distinct_id=None, properties=None, uuid_=None)Any event
identify(distinct_id, email=None, phone=None, properties=None)Attach an identity
purchase(order_id, value, currency="BDT", distinct_id, email, phone, items, uuid_, properties, customer, client_ip, client_user_agent)A conversion
offline(event, value, currency="BDT", order_id, email, phone, distinct_id, action_source="physical_store", properties, uuid_)A conversion that happened outside a browser
flush()Send buffered events
send(events)Send a list of PixelFoxEvent objects you built yourself

Signals and SignalsEvent still work as aliases of PixelFox and PixelFoxEvent for code written against the package's earlier name.

Python is online mode only. Offline mode needs somewhere on your own infrastructure to store analytics, which the WordPress plugin has and an SDK does not.

On this page