Developer notes
Overview · Installation · Configuration · Usage · FAQ
Add-on identity
Section titled “Add-on identity”| Item | Value |
|---|---|
| Add-on ID | kv_order_source_attribution |
| PHP namespace | Tygh\Addons\KvOrderSourceAttribution |
| Tables | cscart_kv_osa_orders, cscart_kv_osa_customers |
| Cookie | kv_osa (first party, path /, SameSite=Lax, Secure on HTTPS) |
| Language variables | kv_order_source_attribution.* |
How it works
Section titled “How it works”dispatch_before_display(storefront, root template) assigns the script configuration;index:footerprints it aswindow.kvOsaConfig,index:scriptsloadsjs/addons/kv_order_source_attribution/func.js.- The script collects UTM tags, click IDs, the external referrer (origin + path, never the query) and the landing page, and keeps the first and the last touch in the cookie (with consent) or in sessionStorage.
- On
checkout.cartandcheckout.checkoutit posts the state tokv_order_source_attribution.capture(only when it changed); the controller validates it and keeps it in the session. place_ordersaves a row for every new order: the session copy or the cookie (the most recent last touch wins), else the referrer core stored when the session started, else direct. Admin orders aremanual, API ordersapi, vendor orders copy the main order.INSERT IGNOREkeeps the original source when an order is edited.- The channel is decided on the server (
Classifier), so the host lists in the settings apply everywhere; Reclassify recomputes stored rows.
Full page cache (4.21)
Section titled “Full page cache (4.21)”The configuration depends only on the storefront settings and the page type, so cached pages are correct for every guest. Storefront GET requests write nothing (no session, no storage_data); the only write is the AJAX POST from the cart and checkout pages, where a session exists anyway.
Consent (Kavio Labs Cookie Consent Mode)
Section titled “Consent (Kavio Labs Cookie Consent Mode)”With Remember sources across visits = After consent, the script uses window.kvConsent.get(<category>) and follows kvConsent.on('change'): a grant moves the state into the cookie, a withdrawal deletes the cookie. The server stores consent = Y/N with each order from fn_kv_cookie_consent_mode_has_consent(). The inline configuration matches the consent add-on’s kv<Name>Config rule and is never blocked.
Hooks used
Section titled “Hooks used”| Hook | File (4.17.2 / 4.21.2) | Purpose |
|---|---|---|
dispatch_before_display |
fn.control.php 623 / 630 | storefront script configuration |
place_order |
fn.cart.php 1585 / 1678 | saves the source of new orders |
get_orders |
fn.cart.php 7810 / 8044 | order list filter (kv_osa_channel, kv_osa_source, kv_osa_medium, kv_osa_campaign, kv_osa_touch, kv_osa_exact) |
get_order_info |
fn.cart.php 2556 / 2657 | kv_source_attribution in REST API order responses |
delete_order |
fn.cart.php 2944 / 3071 | removes the row |
update_profile |
fn.users.php 2639 / 2685 | first source of customers who register on the storefront |
delete_user |
fn.users.php 3403 / 3496 | removes the customer row |
init_templater_post |
upgrade synchronizer (only while pending) | |
before_dispatch (static, License\Client) |
license checks and admin notices |
Template hooks: index:scripts, index:footer (storefront); orders:details_sidebar, orders:manage_header, orders:manage_data, orders:advanced_search, index:styles, addons:tabs_content, addons:manage (admin).
REST API
Section titled “REST API”GET /api/orders/<order_id> contains:
"kv_source_attribution": { "last_touch": {"channel": "paid_search", "source": "google", "medium": "cpc", "campaign": "autumn-sale", "term": "", "content": "", "landing": "/?utm_source=google&utm_medium=cpc&utm_campaign=autumn-sale", "referrer": "", "click_ids": {"gclid": "..."}, "time": 1792000000}, "first_touch": {"channel": "email", "source": "newsletter", "medium": "email", "...": "..."}, "touches": 3, "capture": "cookie", "consent": "Y", "parent_order_id": 0}null when the order has no stored source. Orders created through the API are saved with the channel api.
Storefront script API
Section titled “Storefront script API”window.kvOsa.get() returns the stored state ({v, n, f, l} with the short keys s source, m medium, c campaign, t term, o content, k click IDs, r referrer, p landing page, ts time) or null.
Database tables
Section titled “Database tables”kv_osa_orders: one row per order:capture(cookie, session, server, inherited, admin, api, none),consent,touches, the last touch (channel,source,medium,campaign,term,content,landing,referrer,click_idsJSON,utm,touch_time) and the same fields with the prefixf_for the first touch.kv_osa_customers: the first known source of a registered customer.
License check
Section titled “License check”Tygh\Addons\KvOrderSourceAttribution\License\Client verifies the license against the Kavio Labs license server. The client, the “Check now”/cron controller controllers/backend/kv_order_source_attribution_license.php and the license templates are generated from the shared Kavio Labs template; don’t edit them by hand.
- Admin license UI:
design/backend/templates/addons/kv_order_source_attribution/license/card.tpl(License card, every tab of the add-on page),license/badge.tpl(Add-ons > Manage add-ons),license/status_bar.tpl(first line of the Order sources report),license/info.tpl(License tab),design/backend/css/addons/kv_order_source_attribution/license.less. They render nothing for vendors and for administrators without the Manage settings privilege; templates only read$kv_lic_kv_order_source_attribution. - Gate:
fn_kv_order_source_attribution_is_licensed()(func.php) reads the stored state only. Without a valid license the storefront configuration is not printed (the script does nothing), the capture endpoint stores nothing, andplace_ordersaves no source. The admin panel, the stored data, the report, the order panel and the filters keep working. Checkout is never affected.
File map
Section titled “File map”app/addons/kv_order_source_attribution/ addon.xml, init.php, func.php controllers/frontend/kv_order_source_attribution.php capture endpoint (POST) controllers/backend/kv_order_source_attribution.php report, export, reclassify controllers/backend/orders.post.php order panel, list column and filter data controllers/backend/kv_order_source_attribution_license.php license "Check now" / cron (generated) schemas/menu/menu.post.php, menu_vendor.post.php schemas/permissions/admin.post.php, vendor_multivendor.post.php Tygh/Addons/KvOrderSourceAttribution/ Access.php Attribution.php Classifier.php Config.php Report.php Storefront.php Touch.php License/Client.php License/Ed25519.php Upgrade/Synchronizer.phpdesign/backend/templates/addons/kv_order_source_attribution/ views/kv_order_source_attribution/report.tpl, components/touch.tpl hooks/orders/{details_sidebar,manage_header,manage_data,advanced_search}.post.tpl, license/*design/backend/css/addons/kv_order_source_attribution/{styles,license}.lessvar/themes_repository/responsive/templates/addons/kv_order_source_attribution/hooks/index/{scripts,footer}.post.tpljs/addons/kv_order_source_attribution/func.jsvar/langs/en/addons/kv_order_source_attribution.po