axitrace / module-tracking
AxiTrace server-side tracking for Magento 2 / Adobe Commerce — Facebook CAPI, TikTok Events API, Google Ads offline conversions, GA4. Free module; requires an AxiTrace SaaS account at axitrace.com.
Package info
github.com/axitrace/axitrace-magento-plugin
Type:magento2-module
pkg:composer/axitrace/module-tracking
Requires
- php: ^8.1 || ^8.2 || ^8.3 || ^8.4
- ext-curl: *
- ext-json: *
- magento/framework: ^103.0
- magento/module-catalog: ^103.0 || ^104.0
- magento/module-checkout: ^100.0
- magento/module-config: ^101.0
- magento/module-sales: ^103.0 || ^104.0
Requires (Dev)
- magento/magento-coding-standard: ^40.0
- phpunit/phpunit: ^9.6 || ^10.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Server-side tracking module for Magento 2 / Adobe Commerce stores. Forwards order, product-view, add-to-cart, and other commerce events to AxiTrace, which relays them to Facebook CAPI, TikTok Events API, Google Ads offline conversions, and GA4 - server-side, with deterministic event ids that dedupe against any client-side pixels you may also be running.
The module itself is free under the MIT License. AxiTrace bills the SaaS that processes the forwarded events on axitrace.com (Stripe). There is no module-level licence check or API call back to AxiTrace for billing purposes.
- Magento Open Source: 2.4.6 / 2.4.7 / 2.4.8
- Adobe Commerce (on-prem): same versions
- PHP: 8.1 / 8.2 / 8.3 / 8.4 (per Magento version matrix)
- Themes: Luma (default), Hyva via the separate
axitrace/module-tracking-hyvapackage - Not supported: Adobe Commerce as Cloud Service (ACCS) - uses App Builder, not PHP modules.
Install (Composer - recommended)
composer require axitrace/module-tracking
# Hyva users:
composer require axitrace/module-tracking-hyva
bin/magento module:enable AxiTrace_Tracking Hyva_AxiTraceTracking
bin/magento setup:upgrade
bin/magento cache:clean
Install (ZIP - for hosts without Composer access)
- Download the latest ZIP from axitrace.com/downloads/axitrace-magento-plugin-latest.zip.
- Unzip into
app/code/AxiTrace/Tracking(andHyva/AxiTraceTrackingif you need Hyva support). - Run the same
module:enable/setup:upgrade/cache:cleansequence.
Install (Adobe Commerce Marketplace)
The module is distributed primarily via Composer/Packagist and direct ZIP (above) - no Marketplace account is required to install it. An Adobe Commerce Marketplace listing may be published later for discovery; if/when it is, you will also be able to install with the Marketplace authentication keys from commercemarketplace.adobe.com/customer/accessKeys/.
Configure (under 5 minutes)
- Get your workspace public key: sign in at
axitrace.com/dashboard. Each workspace has
a
pk_live_.../pk_test_...key. Copy it. - Open the Magento admin → Stores → Configuration → AxiTrace.
- Enable AxiTrace tracking: set to Yes.
- Paste your workspace public key. The field is encrypted at rest.
- (Optional) Auto-Detect Domain: if you have a verified custom tracking
domain on AxiTrace, click the button to populate it. Otherwise leave blank
to use the default (
stat.axitrace.com). - Test Connection: the button issues an AJAX request to AxiTrace and shows a coloured status. Green means you're connected.
- Save Config.
- Place a test order in your storefront. Within 1-2 minutes, the Status indicator turns green ("last event N minutes ago") and AxiTrace's dashboard shows the order on the events feed.
What it captures
| Event | Source |
|---|---|
transaction.charge |
sales_order_save_after observer fires on the first state transition into processing. Idempotent via axitrace_event_log UNIQUE constraint. |
view_content |
Storefront pixel on PDP (Luma + Hyva) |
view_category |
Storefront pixel on category page |
product.addToCart |
Storefront pixel via Magento cart events |
begin_checkout |
Storefront pixel on the checkout page, with cart value/currency/item count. Off by default - enable "Checkout started events". |
add_payment_info |
Storefront pixel, best-effort, when the customer reaches the payment step. Off by default - enable "Add payment info events". |
page.view |
Off by default (high volume) |
transaction.refund (credit memo) |
sales_order_creditmemo_save_after observer. Sent only when the AxiTrace secret key is set. |
transaction.refund (cancellation) |
order_cancel_after observer, sent with isCancellation = true. Sent only when the AxiTrace secret key is set. |
PII (email, phone) is forwarded in plain text server-to-server; Facebook's PHP SDK and TikTok's API hash internally per their requirements.
Linking the purchase to the shopper
The purchase is sent from the queue consumer, long after the shopper's request is
gone. So when the order is placed, a sales_order_place_after observer stores the
shopper's browser identity on the order, in the sales_order.axitrace_browser_identity
column (added by setup:upgrade):
- the AxiTrace visitor and session ids (
vt_vid,vt_sidcookies of the AxiTrace JavaScript SDK), sent asuserId/sessionId. This is what links the purchase to the visitor's profile and to the ad clicks of that visitor; - the shopper's IP address and User-Agent;
- the ad platforms' browser ids:
_fbp,_fbc,_ttp,_rdt_uuid,__obref,_ga; - every click id the AxiTrace SDK keeps in a first-party cookie:
gclid,gbraid,wbraid,ttclid,msclkid,twclid(90 days),epik(60 days),li_fat_id(30 days),rdt_cid,opprefandsccid(28 days). A click id in the current URL wins over the stored one (for Snapchat itsScCidparameter, thensccid), unless it repeats a stored click whose window has passed (a bookmarked link); a click older than its window is not sent. When neither has the click, the Microsoft, X, Pinterest and LinkedIn click ids are read from the cookie the platform's own tag sets (_uetmsclkid,_twclid,_epik,li_fat_id), which is never changed.
Only a request from the shopper's own browser is read: the storefront (frontend),
the Luma checkout's REST call (webapi_rest) or GraphQL, and only when the request
carries cookies. An order created in the admin, by a payment webhook or by an ERP
through the API stores nothing, so the merchant's own cookies are never attached to a
purchase. Each value is validated and left out when absent.
Profit tracking (optional)
AxiTrace can report profit and POAS (Profit on Ad Spend) next to revenue and ROAS. To feed it from Magento, paste your workspace secret key into Stores > Configuration > AxiTrace > AxiTrace secret key (optional). In AxiTrace it is under Settings, in the Container Information card, as Secret Key. The field is encrypted at rest, never reaches the storefront and is sent only to an https API base URL. With the key set:
- Purchase events carry each line's unit cost, taken in this order: the order item's cost recorded when the order was placed (for a configurable product the simple product that was bought, then the parent line), then the product's current Cost attribute (the bought product, then its parent). Costs are sent only when the order currency equals the store's base currency; otherwise AxiTrace uses the costs from your AxiTrace cost catalog.
- Credit memos and order cancellations are sent to AxiTrace, where they reduce the order's profit. A full cancellation reverses the whole order, a partial one only the canceled lines; all amounts are gross, in the order currency. Revenue and ROAS stay unchanged.
Every purchase also carries the order tax, the shipping charged (including its tax)
and a product identifier magento:<product id> (the simple product of a configurable
line), whether or not the key is set. If AxiTrace rejects the key, the purchase is
sent again without costs and the error is written to var/log/axitrace.log.
Operations
Logs
All module activity logs to a dedicated file:
var/log/axitrace.log
Critical events (->critical()) also flow through Magento's central log so
they are picked up by any monolog-based alert pipeline.
Idempotency table
The module ships its own table axitrace_event_log (declared via
etc/db_schema.xml):
| column | purpose |
|---|---|
event_id_hash |
UUID v5 from magento_order:{increment_id}; UNIQUE - blocks double-fire on async payment auto-invoice flows |
status |
pending, sent, failed, skipped |
attempts |
retry counter - capped at 5 by the retry cron |
last_error |
truncated error from ingestion-api |
You can inspect it via any DB client; nothing in it should ever be PII.
Cron jobs
Two cron jobs are registered (etc/crontab.xml):
| name | schedule | what |
|---|---|---|
axitrace_consumer_runner |
every minute | spawns the axitrace_order_consumer for up to 100 messages |
axitrace_retry_failed |
every 15 minutes | re-publishes axitrace_event_log rows with status=failed and attempts<5 |
If Magento cron is healthy (bin/magento cron:run runs every minute via system
cron), the module needs zero ops intervention.
Manual retry
bin/magento axitrace:retry-failed
Equivalent effect to one tick of the retry cron - useful after an ingestion-api incident.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
axitrace_event_log empty after placing an order |
Module disabled, or the order didn't transition to processing |
Enable in config; verify the payment method auto-invoices |
Rows stuck in pending |
Magento cron not running | bin/magento cron:run --group=default once; install system cron |
Rows stuck in failed with connection timed out |
Outbound network blocked from your hosting | Allowlist api.axitrace.com:443 |
| Hyva storefront fires no events | Hyva compat package not installed | composer require axitrace/module-tracking-hyva + setup:upgrade |
| Hyva CSP errors in browser console | Hyva FPC + block_html cache stale | bin/magento cache:flush full_page block_html |
Reporting issues
github.com/axitrace/axitrace-magento-plugin/issues
or email info@axitrace.com.
License
MIT - see LICENSE.md.