Changed
- The server reads marketing consent and the ad click from first-party cookies on requests WooCommerce makes anyway, instead of waiting for the browser to send them to
?wc-ajax=egenverk_conversion_relay: every page view andwc-ajaxrequest of a visitor with a WooCommerce session or a login (initpriority 20, before Kustom's confirmation completes a payment at 999), a cart addition, the order review, the checkout and the moment before a payment completes. Cookiebot'sCookieConsentis parsed by the plugin itself:-1(a visitor outside a consent region, which Cookiebot's script also reports as a grant) is a grant,0a refusal, and otherwise only themarketingflag of the object Cookiebot writes is read, up to 4 kB; anything else is unknown. WP Consent API'swp_consent_marketingcookie is read directly, becausewp_has_consent()on the server grants when no consent type is set or, in an opt-out region, when there is no cookie:denyis a refusal,allowa grant only whenwp_has_consent()agrees, anything else unknown. The click comes from the pixel SDK's__oppref, which the SDK replaces on every ad landing, then from the plugin's own cookieegenverk_conversion_relay_click, and the browser reference from__obref; each is checked like the endpoint checks them, and must be valid UTF-8. - The consent record is written through the same path as the endpoint, so a refusal still withdraws queued purchases at once, but only when consent or the click changed, or when the record has less than two days left; a copy in the WooCommerce session answers every other request without reading the record (a logged-in customer without a session cookie gets no copy, so no session is stored for it). No session is ever opened for this, unknown consent never changes a record, a refusal waits up to five seconds for a record another request holds, and a click the granted record holds is kept when the cookies lack it, as the browser keeps it until a refusal.
- A cart addition queues its
items_addedevent when the consent cookie in that request grants, instead of requiring a record an earlier request had stored. - The response to a granted cart addition hands the session's additions of the last two minutes to the browser in a two-minute cookie,
egenverk_conversion_relay_added(host-only, not HttpOnly,SameSite=Lax,Secureon https, path/), each with the event id the server generated, the product and variation, quantity, amount and currency. Carrying every recent addition, rather than the ones the request brought back, keeps an addition whose answer the browser had not read when the next one was posted, and never sets again what the browser sent. The value is at most 1 kB encoded: product names are dropped first, then an addition too large on its own, then the oldest; when nothing fits the cookie is removed. The script reads it onadded_to_cart,wc-blocks_added_to_cartand when a page loads, which covers an addition that reloads the page, measuresitems_addedwith each event id it has not measured in the last five minutes, and removes the cookie. With refused consent, the pixel off or the event not selected it removes it unmeasured; while consent is unknown, or another script owns the pixel SDK, it leaves it. A refusal the server sees removes it. A refusal also forgets the ids measured, and empties the session's additions, so a later grant does not hand earlier ones over. - An order is stamped with the consent in the checkout request's own cookie; an order placed without a readable consent cookie is
unknown, whatever an older record says. The session's unpaid order is re-stamped on every order review and consent change, never above what the request's cookie says. Every capture, through the payment or a paid status, now needs that stamp to be a grant as well as the record, and none happens in a request whose consent cookie refuses. A grant that reaches the server only after the payment completed no longer makes the purchase count, as it could through the payment until now: consent is taken as it was when the order was placed and paid. - The ad click from the landing URL is kept in the first-party cookie
egenverk_conversion_relay_clickas<expiry>.<click>(host-only, path/,SameSite=Lax,Secureon https, not HttpOnly), 30 days from the click, instead of inlocalStorage, which the server cannot read. The script writes it only with a grant and never writes the same click again, so a reload does not extend it; a click 1.3 kept inlocalStoragemoves to the cookie with its expiry. With a grant and a click the server sets the same cookie, since Safari keeps a cookie a script writes for seven days only. The expiry it carries is kept in a new session or for a new account, a click only the pixel SDK's__opprefcarries keeps the expiry the session saw before, and a cookie the browser already holds is not sent again. A refusal removes it on both sides. - While the server keeps a grant for the browser it sets two marker cookies until the record expires, host-only,
SameSite=Lax,Secureon https:egenverk_conversion_relay_record, HttpOnly, which names the record with a signature, andegenverk_conversion_relay_marker, which the script reads and which holds only the expiry, so no script sees a stable identifier. A refusal made on a page, which the next request WooCommerce makes would carry anyway, is sent at once as one small request (client: 4,action: refuse, withkeepalive, so it survives the tab being closed) when the server may hold a grant: with a cart, a login or that marker. It is sent once per change to a refusal on that page, and on start-up for a refusal made before the script ran while the marker is there; never for a refusal the page request itself carried, and never in answer to another tab. The HttpOnly marker's signed reference to the record lets the refusal reach it after the WooCommerce session has expired, as it does two days after a guest's last visit; it is signed with a key derived from the auth salt, so rotating the salts invalidates every marker, which is then ignored and removed, and such a late refusal is dropped while the record expires by itself. The endpoint answers the refusal with an empty result, never throttles it, removes both markers, and ignores it when the request's consent cookie grants again; the script then sends a refusal made before it started at most once per marker value in a tab session. The order received, pay-for-order and account pages, where nothing is measured, carry the script in a refusal-only mode: no pixel, no page events and no cart additions, only the refusal and its cleanup. - The script no longer sends grants, clicks, cart and login changes, the preparation before the first cart addition, the daily and 30-minute repeats or the forced sync before checkout, and it no longer listens to other tabs. The synchronization state older versions kept in
localStorage(egenverk_conversion_relay_synced,egenverk_conversion_relay_grantedand their first names) is removed on the first page view. The pixel, the page events, the configuration in the page and the diagnostics are unchanged. A page cached with HTML from before 1.2.1 measures nothing until the page cache is purged. - The endpoint still answers scripts from 1.2.x and 1.3.x (
client2 and 3) as before for one version, since pages and browser caches keep them for a while: grants, clicks, refusals, the cart preparation and the throttling. That code goes in 1.5.0. - A refusal the record lock kept from being stored is logged as a warning (
consent_lock_busy). - A guest who logs in or creates an account at checkout takes the consent record and click to the account (WooCommerce 8.8 and later), unless the account holds a newer record.
Fixed
- The changelog of 1.2.1 and 1.3.2 promised one synchronization before an order is placed, so that a refusal made on the checkout page reaches the server first. The script hooked WooCommerce's
checkout_place_orderevent on the checkout form, but Kustom Checkout posts the order straight to?wc-ajax=checkoutfrom its own script, so that event never fires and the synchronization never ran for an order placed through Kustom: a refusal made on its checkout page after an earlier grant could leave the order stamped with the grant. The checkout request itself now carries the consent cookie, and the order and the record are both written from it in that request, whichever script posts the order; the hook is gone. A refusal made after the order was placed is read on Kustom's confirmation page before that request captures the payment; if Kustom's server push captured it first, the refusal withdraws the queued purchase if it reaches the server before the purchase is sent, a few seconds after payment. - Since 1.0.0 a purchase captured through
woocommerce_payment_completeor Kustom's payment callback was decided by the customer's consent record alone, never by the consent recorded on the order when it was placed, so an order placed with consent unknown or refused was still exported when an older grant was on record. Only the paid-status path (1.2.0) checked the order.