Ecommerce
Magento / Adobe Commerce
Send orders to OrcLink from the OrcLink Magento module or an Adobe Commerce webhook. Each paid order becomes an order outcome.
Live: shipped in OrcLink's production release before this one. Built, not yet tested live: built and tested with sample data, not yet run against a live account of the vendor. Coming soon: listed, not available to connect yet.
How to connect
- Dashboard > Integrations > Magento / Adobe Commerce > Connect. Copy the webhook URL and the secret (shown once) into Magento / Adobe Commerce.
What OrcLink reads
- Orders pushed by the OrcLink Magento module (or an Adobe Commerce webhook).
What OrcLink writes back
- The module saves the click id (olid) on the order.
Never stored
- Raw email addresses and phone numbers: hashed (SHA-256) the moment they arrive.
- The raw payload: only its SHA-256, for provenance.
- Your credentials and webhook secrets in clear: they are stored encrypted (AES-256-GCM).
Known limits
- The module was never installed on a real store; see the table below for what is and is not built.
UNTESTED on a real store. The adapter (app/lib/outcomes/sources/magento.ts) is tested against a fixture built from the public shape of a Magento order; the module is a skeleton that was never installed or syntax-checked (no PHP in the build environment).
What is built, and what is not
| Magento Open Source | Adobe Commerce | |
|---|---|---|
| Native order webhooks | none | the Adobe Commerce webhooks module (App Builder) |
| How orders reach OrcLink | the OrcLink module's observer (sales_order_save_commit_after) posts each save | the module (same), or an Adobe Commerce webhook |
| Built | module skeleton, adapter, route | adapter and route accept the secret as a header; no webhook definition file is shipped |
| NOT built | a queue or retry for the push (one send after the response, 1 s connect / 2 s total timeout, lost if it fails), a cron re-push of missed orders, any admin grid column, MFTF/PHPUnit tests, Marketplace packaging | the webhook definition for Adobe Commerce; its payload shape is not verified |
Adobe Commerce native webhooks send Magento's own created_at ("Y-m-d H:i:s", no zone). OrcLink does not read a time without a zone, so such an order is ignored and the OrcLink Integrations page shows a fixed note. Either keep the module's push (it sends ISO 8601 with Z) or configure the webhook to send a time with a zone / created_at_utc.
1. Connect in OrcLink
Dashboard > Integrations > Magento / Adobe Commerce > Connect. Copy the webhook URL and the webhook secret (shown once).
2. Install the module
Copy integrations/magento/Orclink/Attribution/ to app/code/Orclink/Attribution/, then:
bin/magento module:enable Orclink_Attribution bin/magento setup:upgrade bin/magento cache:flush
setup:upgrade adds the column orclink_olid to quote and sales_order (etc/db_schema.xml). Then Stores > Configuration > Sales > OrcLink: workspace id, tag domain, the webhook URL, the webhook secret (stored encrypted) and the Test store flag.
The module:
- prints
<script async src="https://<tag domain>/t.js?w=<workspace id>" data-w="...">in<head>; - on
sales_quote_save_before(in the storefront, and in the REST and GraphQL areas that Luma's and PWA checkouts place orders through) copies theorc_olidcookie (written by/t.jsafter advertising consent) toquote.orclink_olid; with no valid cookie (none, consent withdrawn, expired, or a value that is notol_+ 32 hex) it clears the quote's value on the shopper's own browser request (Sec-Fetch-Site: same-originornone), so the quote never keeps an older click id. A cross-site return from a hosted payment page (noSameSite=Laxcookie) does not clear it.etc/fieldset.xmlcarries it to the order. No cookie = no olid = the order is recorded unattributed; - on
sales_order_save_commit_afterbuilds the order as JSON and sends it to the webhook URL, signed:X-Orclink-Signature: sha256=<hex HMAC-SHA256 of the raw body>. The send is not made inside the order save: the module queues it in memory and sends it when the request ends, afterfastcgi_finish_request()where PHP-FPM provides it (so the shopper's response is already sent; without PHP-FPM it still runs after the page is built, but the response is not released early). Connect timeout 1 s, total timeout 2 s. It never throws into the save. Several saves of one order in one request send once. - It observes
sales_order_save_commit_after(after the database transaction commits), so no push goes out for an order whose save rolled back. - In CLI and queue-consumer contexts (cron,
bin/magento, message-queue workers) the deferred send runs at process exit, and is lost if the process is killed before then. - There is no queue and no retry. If OrcLink is down or slow, that push is lost; the next save of the order (invoice, shipment, credit memo) sends the state again.
- The body carries the order's customer email and the billing phone number. OrcLink hashes them on receipt and does not store them raw. It is used only to match a later outcome to the same click.
orclink_test: trueonly when the config setting Test store (Stores > Configuration > Sales > OrcLink, default No) is Yes. Developer or default mode does not mark orders as test orders. Set it to Yes on a staging store that shares the live webhook URL.
Uninstall
bin/magento module:uninstall Orclink_Attribution (a Composer install) runs Setup/Uninstall.php: it drops the orclink_olid column of quote and sales_order and deletes the module's configuration (orclink/*, the encrypted secret included). For a copy in app/code, disable the module, delete the folder and drop the two columns and the orclink/% config rows by hand.
3. Adobe Commerce webhook instead (optional)
Create a webhook for the order-save event that posts the order to the OrcLink webhook URL with the header X-Orclink-Secret: <the secret> (or Basic auth, any user, the secret as the password). The order is read from the top level, order or data.order.
One Magento instance per connection. The module sends the instance's id: the DEFAULT scope's base URL (orclink_store), the same for every store view and website of the instance (they share one order id space, so they are one store for OrcLink). OrcLink binds the connection to the first one it sees and refuses orders of another instance with a fixed note. If the instance moves to a new base URL, or the wrong instance delivered first, use Allow another store on the OrcLink card (a manager action, audited): the next order binds it again. An Adobe Commerce webhook that does not send orclink_store is not checked.
What OrcLink does with an order
Magento state | OrcLink |
|---|---|
complete; processing with nothing due (total_due 0; without it, total_paid covering grand_total) | order won (paid), value = grand_total in order_currency_code |
processing with money still due (an authorised, not captured payment) | open |
new, pending_payment, payment_review, holded | open |
canceled | cancelled |
closed | won, net value 0 |
credit_memos[] (entity_id, grand_total) | one revision per memo that lowers net value |
only total_refunded | one revision for the part of the total not yet stored |
| any other state | ignored; the integration shows a fixed note |
Late pushes and edited totals
A push can arrive late, and it carries the order as it was when it was saved. So once an order is won in OrcLink, a later push does not change its stored total (refunds, credit memos and cancellations still apply). A total edited after payment is not picked up; in Magento an edit is a new order. An order that is still open takes each push's total until it is paid.