hirale / openmage-meta-conversions
Meta Conversions API integration for OpenMage and Maho, dispatching through core Maho_Queue on Maho and hirale/queue on OpenMage.
Package info
github.com/hirale/openmage-meta-conversions
Type:magento-module
pkg:composer/hirale/openmage-meta-conversions
Requires
- php: >=8.3
- facebook/php-business-sdk: ^25.0
- jaybizzle/crawler-detect: ^1.2
Requires (Dev)
- phpunit/phpunit: ^10.5
- symfony/messenger: ^7.4 || ^8.0
Suggests
- hirale/queue: ^3.0 — the queue backend on OpenMage; required there, unused on Maho, which dispatches through the core Maho_Queue module
- magento-hackathon/magento-composer-installer: Deploys extra.map into the OpenMage project (resolves at 1.3.2; see the hirale/queue README — Maho needs no installer plugin)
- mahocommerce/maho: ^26.5 — the Maho platform (alternatively openmage/magento-lts >=20.17)
Provides
None
Conflicts
- mahocommerce/maho: <26.5
- openmage/magento-lts: <20.17
Replaces
None
This package is auto-updated.
Last update: 2026-09-08 11:48:39 UTC
README
A module for integrating Meta Conversions API, sending events from server side.
Deduplicating against the browser Pixel
If the storefront also fires the Meta Pixel, the same action reaches Meta twice
— once from the browser, once from this module. Meta collapses the pair only
when both carry the same event_id, keyed on (event_name, event_id);
see Meta's guide.
Reserve the id in the template that emits the Pixel call, and the observer attaches the same one to the queued server-side event:
<?php $eventId = Mage::helper('metaconversions')->reserveEventId('ViewContent'); ?> <script> fbq('track', 'ViewContent', { /* ... */ }, { eventID: '<?php echo $eventId ?>' }); </script>
Reserve nothing and the module still works — it generates its own id — but Meta then counts the browser and server events separately.
Supported Events
AddToCartAddToWishlistCompleteRegistrationInitiateCheckoutPurchaseSearchViewContentPageViewViewCart
You can check more events in the events section.
Queue backend
Events are never posted from the request that generated them: the observer hands one message per request to a queue and a worker uploads the batch. There is no shared queue package any more — the module picks a backend at runtime, in this order:
| Platform | Backend | Package to install |
|---|---|---|
Maho with the core Maho_Queue module |
\Maho\Queue\QueueManager |
none — it ships with the platform |
| OpenMage | \Hirale\Queue\Bus |
hirale/queue ^3.0 |
| Neither | — | events are not queued; the storefront is unaffected |
Maho_Queue wins whenever it is present and enabled, even on a store that also
has hirale/queue installed.
Messages ride the analytics queue on both platforms. On Maho, config.xml
routes that queue to the catch-all slow pool, so a CAPI upload — one outbound
HTTP call that can block on Meta — never competes with the resident fast pool
that carries order mail. A host can retarget it from its own config.xml or
local.xml.
3.0.0 is a breaking change.
hirale/queuemoved fromrequiretosuggest. OpenMage installs that upgrade from 2.x must require it explicitly, or events stop being queued. Nothing else changes: the same events, config paths andanalyticsqueue name as before.
Install
Maho (26.5+, with core Maho_Queue):
composer require hirale/openmage-meta-conversions composer dump-autoload
composer dump-autoload is required: it compiles the
#[\Maho\Config\MessageHandler] attribute into
vendor/composer/maho_attributes.php. Without it the message has no registered
handler, and the queue refuses to decode it.
OpenMage (20.17+, PHP 8.3+) — one-time tweaks first; details in the hirale/queue README:
composer config platform.php 8.3
composer config allow-plugins.hirale/magento-module-installer true
composer require hirale/magento-module-installer hirale/queue hirale/openmage-meta-conversions
Usage
Setup
- Make sure a queue backend is configured and its worker is running (see Queue backend) — on OpenMage that is
System > Configuration > Hirale > Queue, on Maho the core queue needs no setup beyond a running worker. - Generate an access token. See https://developers.facebook.com/docs/marketing-api/conversions-api/get-started.
- Go to system config
System > Configuration > Sales > Meta API > Conversions API. Insert the parameters from step 1, save.
Event reporting rules
- Route events (
PageView,Purchase,InitiateCheckout,ViewCart,ViewContent,Search) are reported only from a rendered200HTML response. A redirect, a JSON endpoint or an error page reports nothing — an empty cart bounced back from checkout is not anInitiateCheckout. Purchaseis reported once per order. A reloaded success page returns a redirect, which the rule above already stops; on Maho a mark on the checkout session backs that up. On OpenMage that mark is not persisted — the platform closes the session beforecore_app_run_afterdispatches — so there the redirect rule is the only thing preventing a duplicate. Meta cannot absorb such a duplicate on its own: every dispatch mints its ownevent_id, and deduplication is keyed on (event_name,event_id).- An observer that fails while building a payload logs and gives up. It never interrupts the action it is measuring: a cart save, a registration.
- A store with no access token or pixel id logs one line per dropped batch, whether or not debug mode is on.
Debug
Enable Debug Mode in system config, then check var/log/meta_conversions.log.
Each processed queue message logs two entries: the event batch (envelopes +
custom data — user_data is deliberately never written to logs, and PII is
already SHA-256 hashed before it even reaches the queue) and the Graph API
response.
Permanent errors fail the queue job immediately and show up in the queue's
failure list; transient errors retry with backoff. Permanent means a replay
cannot succeed: an invalid or revoked access token, a missing permission, a
duplicate post, or any other 4xx from the Graph API. Rate limiting (Meta
answers 400 for it), 5xx and network failures retry.
2026-06-11T10:00:00+00:00 DEBUG (7): Array
(
[store_id] => 1
[events] => Array
(
[0] => Array
(
[event] => Array
(
[event_time] => 1718044092
[event_source_url] => https://example.com/some-product.html
[action_source] => website
[event_id] => 666745bcdd76a
[event_name] => ViewContent
)
[custom_data] => Array
(
[currency] => USD
[content_type] => product
[content_ids] => Array ( [0] => SKU-9 )
)
)
[1] => Array
(
[event] => Array
(
[event_name] => PageView
)
[custom_data] =>
)
)
)
2026-06-11T10:00:00+00:00 DEBUG (7): FacebookAds\Object\ServerSide\EventResponse Object
(
[container:protected] => Array
(
[events_received] => 2
[messages] => Array ( )
[fbtrace_id] => AkuJqnm2pr421jM7d89SRqa
)
)
Upgrading
- The access token is now stored encrypted (
adminhtml/system_config_backend_encrypted). After upgrading, re-enter and save the token once in system config. - The queue message schema changed (one message now carries all events of a request, and PII is hashed before enqueueing). Let the queue worker drain pending metaconversions messages before deploying the upgrade; messages enqueued by the old version cannot be processed by the new handler.
License
The Open Software License v. 3.0 (OSL-3.0). Please see License File for more information.