WooCommerce Integration Guide
The Loxa WooCommerce plugin is a turnkey integration that handles insurance display, cart management and order data — no custom frontend or backend code required. Install the plugin, configure your API key in WooCommerce settings, and Loxa Product Protection appears on your product pages automatically.
You can see the plugin in action on our WooCommerce Test Store. Three insurance integration types are supported: Add-on, Inclusive and Hybrid (inclusive cover with a paid extension). For details on what each type means, see the Generic Integration Guide.
The badge and sidebar use the same design as our Magento, Shopify and BigCommerce integrations, so shoppers see the same Loxa experience on every platform.
Requirements
| Requirement | Version |
|---|---|
| WordPress | 5.8+ |
| WooCommerce | 7.0+ |
| PHP | 7.4+ |
The plugin is compatible with WooCommerce's High-Performance Order Storage (HPOS) and the Cart & Checkout Blocks, as well as the classic cart and checkout.
Installation
This link always gives the latest release of the plugin.
Upload the plugin ZIP file through the WordPress admin:
- Go to Plugins > Add New Plugin > Upload Plugin.
- Select the ZIP file provided by Loxa and click Install Now.
- Click Activate.
Alternatively, extract the ZIP to your wp-content/plugins/ directory and activate from the Plugins screen.
Updating the plugin
To update, download the latest ZIP above and upload it the same way. WordPress asks whether to replace the installed version; your settings are kept.
Generate the Insurance Product
The plugin uses a hidden virtual product (loxa-insurance) as the line item for insurance in the cart. You need to generate this product once after installation.
- Go to WooCommerce > Settings > Integration > Loxa Insurance.
- Under Product Page, check the Generate Insurance Product checkbox.
- Click Save changes.
This creates a virtual product with SKU loxa-insurance, base price 0.00, not visible in the catalog. Each insurance line in the cart is priced with the premium from its own quote, so several products with different premiums can be covered in the same basket.
Required step
Insurance cannot be added to the cart until this product exists. If the product is missing, customers will not see insurance options on product pages.
Configure the API
Navigate to WooCommerce > Settings > Integration > Loxa Insurance and fill in the following fields under API Configuration:
| Field | Description |
|---|---|
| Enable | Must be checked to activate the plugin |
| API Key | Your API key provided by Loxa. Once saved it is never shown again; leave the field blank to keep it, or enter a new key to replace it |
| Environment | Test while you set up, Live to sell real cover. Selects the Loxa API used for quotes and orders — there are no URLs to enter |
Quote signing is automatic
Every quote the plugin receives is signed on your server and checked again when the customer adds to cart, so the premium charged is always the premium Loxa quoted. There is nothing to configure — the signing key is derived from your WordPress site's own security keys.
How It Works
Once installed and configured, the plugin handles the full insurance lifecycle automatically:
┌─────────────────────────────────────────────────────────────────────┐
│ PRODUCT PAGE (browser) │
│ │
│ 1. Page loads → PHP injects product data and settings as JSON │
│ 2. JS asks your server for a quote (wp-admin/admin-ajax.php), │
│ sending only product identifiers — never a price │
│ 3. Your server looks up the product's price itself, adds the API │
│ key and asks the Loxa API for a quote │
│ 4. Your server signs each quoted plan to the product it is for │
│ 5. JS renders the insurance badge and sidebar │
│ 6. Customer adds cover → clicks "Add to Cart" │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ SERVER (WooCommerce) │
│ │
│ 7. Cart handler checks the quote's signature against the product │
│ actually being added — a tampered or stale quote is refused │
│ and the customer is told cover wasn't added │
│ 8. Insurance is added as its own line, linked to that product's │
│ line, at the quoted premium │
│ 9. Insurance quantity always follows its product line │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ CHECKOUT → ORDER │
│ │
│ 10. Plugin copies insurance data to order item meta │
│ (_loxa_insurance_data, accessible via the REST API) │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ ORDER PROCESSING │
│ │
│ 11. The order reaches Loxa — Loxa reads it from your store, or │
│ the plugin sends it (see Order Processing) │
│ 12. Loxa creates the policies │
│ 13. Customer receives their welcome email and policy documents │
└─────────────────────────────────────────────────────────────────────┘
What the Plugin Handles Automatically
You do not need to build any of the following — the plugin takes care of it:
- Badge rendering — add-on, inclusive and hybrid badges in Loxa's standard design. The hybrid badge states the free cover and offers the paid extension in one card.
- Insurance sidebar — plan picker, terms, FAQ and legal disclaimers, with the decision kept in view while the details scroll. On mobile it opens as a bottom sheet. It is keyboard- and screen-reader-accessible.
- Variant re-pricing — when a customer selects a different variation (size, colour, etc.), the plugin quotes that variation at its own price.
- Price protection — premiums are signed server-side and verified on add-to-cart, so they can't be changed in the browser. Prices are always looked up on your server, never taken from the browser.
- Cart line item management — each insured product gets its own insurance line at the correct premium. Units added with cover and units added without stay on separate lines, so customers are never covered for items they didn't choose cover for. Removing an insured product removes its insurance.
- Quantity synchronisation — insurance quantity follows its product line and can't be changed on its own, in both the classic and block cart.
- Coupon exclusion — coupons never discount the premium, including basket-wide (fixed cart) coupons.
- Second-chance mechanism — optionally intercepts add-to-cart when the customer hasn't chosen cover and shows the sidebar as a reminder (configurable in settings). It only does so when there is cover to offer.
- Quote-to-order persistence — insurance data follows the order through checkout and is accessible on the completed order via the REST API.
- Compliance — opt-out flows for inclusive insurance are built in per Compliance Rules.
- Catalog visibility — the insurance virtual product is hidden from the shop catalog and search results.
- Bundles and composite products — for Product Bundles, Composite Products and Mix and Match, only options the product actually offers are priced, and cover quoted for a cheaper configuration isn't accepted for a dearer one.
- Quote caching and limits — a quote is reused for 5 minutes for the same product and price, so busy pages don't call Loxa on every view (clear it from the settings with Clear cached quotes), and calls to Loxa are rate limited per visitor and store-wide.
- Post-purchase offers (optional) — items too expensive to protect at checkout can be offered protection by email after purchase. See Items Above the Point-of-Sale Limit.
Order Processing
When a customer checks out with insurance, the plugin saves the insurance data on the order. Loxa then creates the policies. How the order reaches Loxa is agreed with Loxa during onboarding — your store uses one of these:
| Method | How it works | What you set up |
|---|---|---|
| Loxa reads your orders | Loxa periodically retrieves new orders containing insurance from your WooCommerce REST API | WooCommerce REST API keys, shared with Loxa (below) |
| The plugin sends your orders | The plugin sends each protected order to Loxa as soon as it is paid or completed | The Send Orders to Loxa setting (below) |
REST API keys
To let Loxa read your orders, create WooCommerce REST API keys:
- Go to WooCommerce > Settings > Advanced > REST API.
- Click Add key.
- Give it a description (e.g. "Loxa").
- Set the User to an administrator account.
- Set Permissions to Read.
- Click Generate API key.
- Share both values with Loxa:
| Credential | Description |
|---|---|
| Consumer Key | Identifies the API client (starts with ck_) |
| Consumer Secret | Authenticates API requests (starts with cs_) |
Copy the keys immediately
The Consumer Secret is only shown once when generated. If you lose it, you will need to revoke the key and create a new one.
Keep these credentials secure
These values grant read access to your order data. Share them with Loxa through a secure channel — never send them over plain email or commit them to version control.
Sending orders from the plugin
Set Send Orders to Loxa (under Orders in the plugin settings) to choose when each protected order is sent:
| Option | When it is sent | Cover starts |
|---|---|---|
| Off (default) | Never — use this if Loxa reads your orders | — |
| When the order is paid | When the order reaches a paid status (Processing or Completed). Bank transfer and cash-on-delivery orders are sent once you confirm payment | On the purchase date |
| When the order is completed | When you mark the order Completed | On the completion date — use this for made-to-order or long-lead items, so cover doesn't start before the customer has the product |
Orders are sent in the background, so checkout is never slowed down. If Loxa can't be reached, the plugin retries automatically over several hours.
Each order gets a private order note recording the outcome — for example "Loxa: sent for policy creation (2 protected items)". If an order couldn't be sent, the note says so, and you can retry it from the order screen with Order actions > Send to Loxa (create policy).
No real customer data in Test
While the Environment is Test, orders are sent with a placeholder customer in place of the real name, email, phone and address. Real customer details are only ever sent to the Live API.
Insurance data on order items
Each insurance line on an order carries the _loxa_insurance_data meta, available on order line items via the REST API:
Example order line items (GET /wp-json/wc/v3/orders/:id)
{
"line_items": [
{
"name": "3 Seater Sofa",
"sku": "sofa-3-seater",
"quantity": 1,
"price": 1299.99
},
{
"name": "Loxa Insurance",
"sku": "loxa-insurance",
"quantity": 1,
"price": 101.99,
"meta_data": [
{
"key": "_loxa_insurance_data",
"value": {
"code": "LDF5-20260119-23",
"premium_raw": "101.99",
"name": "Product Protection",
"term": "5",
"sum_insured": "1299.99",
"inclusive_code": "",
"parent_sku": "sofa-3-seater",
"parent_cart_key": "6512bd43d9caa6e02c990b0a82652dca",
"parent_name": "3 Seater Sofa"
}
},
{
"key": "_loxa_insurance_code",
"value": "LDF5-20260119-23"
}
]
}
]
}
| Field | Description |
|---|---|
code |
The insurance plan code (used by Loxa to identify the policy) |
premium_raw |
Premium charged to the customer, per unit |
name |
Plan display name |
term |
Coverage term in years |
sum_insured |
The insured product's price at time of purchase |
inclusive_code |
For a hybrid order, the code of the free cover the paid extension builds on; empty otherwise (also stored as _loxa_inclusive_code) |
parent_sku |
SKU of the product being insured |
parent_name |
Name of the product being insured |
parent_cart_key |
Internal cart key linking insurance to its product line |
Every value is set on your server from the verified quote and the cart — nothing is taken from the browser unchecked.
For post-purchase offers, a product line the customer ticked carries _loxa_post_purchase_interest = yes (plus a visible Product protection line), and the order records the offer in _loxa_post_purchase_offer (queued, sent, not_eligible or failed) and _loxa_post_purchase_offer_link (the offer link and its expiry).
Cancellations
The plugin does not send cancellations or refunds to Loxa. Loxa picks these up from your orders. If you need to notify Loxa of a cancellation outside that flow, you can use the Cancellations endpoint directly.
Items Above the Point-of-Sale Limit
Some plans have a point-of-sale limit: above a set price they can't be bought at the checkout. Those items can still be protected after purchase, up to the plan's limit of indemnity, if post-purchase is enabled for your store by Loxa.
This is optional. Turn it on with Post-Purchase Protection Offers under Orders in the plugin settings (off by default).
For those items the product page shows, in place of the badge:
☐ Click here if you're interested in product protection This item can't be protected at checkout. Tick the box and we'll email you your protection options after your order. Learn more →
Learn more opens the sidebar with the plan's description — no plans, prices or terms, as nothing is on sale yet.
When the customer ticks the box and checks out:
- The item is marked in the basket and on the order: "Product protection: We'll email you your options after your order".
- Once the order is paid, the plugin asks Loxa for a post-purchase offer for the ticked items — the order number, product SKU, name and price only. No customer details are sent to Loxa.
- If anything can be protected, your store emails the customer a link to choose and buy cover from Loxa. The link lasts 30 days.
This happens whatever Send Orders to Loxa is set to.
Each order records what happened in its order notes, and Order actions > Send post-purchase offer (Loxa) sends it again — the customer gets the same link while it's still valid.
The offer email
The email is a standard WooCommerce email, Product protection offer in WooCommerce > Settings > Emails. It lists the items, a View your protection options button, the date the link expires, a note that there's no obligation to buy, and Loxa's regulatory disclaimer.
| To change | Where |
|---|---|
| Logo, colours, font and footer | WooCommerce > Settings > Emails — the store-wide email styling, shared with your order emails |
| Subject, heading, extra text, HTML or plain text | WooCommerce > Settings > Emails > Product protection offer |
| Layout and wording | Override the template in your theme. Copy file to theme on the email's settings screen copies it to yourtheme/woocommerce/emails/loxa-post-purchase-offer.php (and emails/plain/… for plain text); plugin updates never overwrite your copy |
| Extra CSS for all WooCommerce emails | The woocommerce_email_styles filter |
Turning the email off also removes the tickbox from product pages — ticking it promises an email.
Keep the required wording
If you override the template, keep the no-obligation line and Loxa's legal disclaimer, and don't describe the cover yourself: what's covered, the price and the documents are shown on Loxa's offer page.
Your store must be able to send email
The offer is sent by your store, the same way as your order confirmations. If your store has no mail service set up (common on staging and test sites), the order note says the email could not be sent. Set up an SMTP or transactional email plugin, then use Order actions > Send post-purchase offer (Loxa).
Post-purchase must be enabled
The tickbox only appears when Post-Purchase Protection Offers is on and Loxa has enabled post-purchase for your store. Turning the setting off removes the tickbox; orders already placed with the box ticked still receive their offer. See the Post-Purchase Integration Guide for how post-purchase cover works.
Theme Compatibility
The plugin is designed to work with standard WooCommerce themes. It injects anchor elements into the product page using WooCommerce's woocommerce_single_product_summary hook and renders the sidebar in wp_footer.
| Theme | Status | Notes |
|---|---|---|
| Storefront (and Storefront-based) | Standard WooCommerce hooks are present | |
| Block themes | Anchor elements injected via hooks; block cart and mini-cart supported | |
| Custom themes | See below |
The badge and sidebar are protected from your theme's own styles, so a theme's button or link styling won't restyle them. To match your brand, use the Custom CSS setting.
For custom themes that restructure the product page or use non-standard selectors for the add-to-cart button, quantity input or variant pickers, you can configure the relevant CSS selectors in the plugin settings. To place the badges somewhere specific, set the Add-on Anchor Selector / Inclusive Anchor Selector — the badge is inserted after the element they match.
If your theme does not render the standard WooCommerce product summary hooks, you can manually add the anchor elements to your template:
<span id="loxa-woocommerce-inclusive-anchor" data-loxa-woocommerce-anchor="inclusive"></span>
<span id="loxa-woocommerce-addon-anchor" data-loxa-woocommerce-anchor="addon"></span>
Admin Configuration Reference
All settings are located at WooCommerce > Settings > Integration > Loxa Insurance.
API Configuration
| Field | Default | Notes |
|---|---|---|
| Enable | Off | Activates the plugin |
| API Key | (empty) | Provided by Loxa. Never shown once saved; blank keeps the saved key |
| Environment | Test |
Test or Live; selects the Loxa API for quotes and orders |
Product Page
| Field | Default | Notes |
|---|---|---|
| Insurance Product ID | (set automatically) | Read-only; filled in when the insurance product is generated |
| Generate Insurance Product | Off | Check and save to create (or recreate) the insurance product |
| Add to Cart Selector | .single_add_to_cart_button |
CSS selector for the add-to-cart button |
| Variant Selector | (empty) | Optional CSS selector for custom variant pickers |
| Quantity Selector | input[name="quantity"] |
CSS selector for the quantity input |
| Buy Now Selector | (empty) | Optional; for express checkout buttons that submit the product form |
| Add-on Anchor Selector | (empty) | Optional; the add-on / hybrid badge is inserted after this element |
| Inclusive Anchor Selector | (empty) | Optional; the inclusive badge is inserted after this element |
Behavior
| Field | Default | Notes |
|---|---|---|
| Sidebar Position | right |
left or right (desktop; on mobile the sidebar opens from the bottom) |
| Second Chance | Off | Shows the sidebar if the customer clicks add-to-cart without choosing cover |
| Variant Delay (ms) | 0 |
Debounce in ms before re-quoting on variant change |
| Variant ID Source | auto |
How to detect the selected variant; auto covers most themes |
| Exclusion Tags | (empty) | Comma-separated category or tag names to exclude from insurance |
| VAT Excluded | Off | Enable if catalog prices exclude VAT; products are insured at the price plus 20% |
| Category Override | Off | Prices products in the Loxa category named by their first category or tag prefixed with loxa- (e.g. loxa-garden-furniture). Worked out on your server, never in the browser. Must be agreed with Loxa before use — Loxa also enables category override for your store, otherwise the category is ignored. |
Orders
| Field | Default | Notes |
|---|---|---|
| Send Orders to Loxa | Off |
Off, When the order is paid or When the order is completed — see Sending orders from the plugin |
| Post-Purchase Protection Offers | Off | Offers protection after purchase for items too expensive to protect at checkout — see Items Above the Point-of-Sale Limit |
Appearance
| Field | Default | Notes |
|---|---|---|
| Show Sidebar on Add | Off | The badge's Add / Extend button opens the sidebar instead of adding cover straight away |
| Show FAQ in Sidebar | On | Shows Loxa's standard frequently-asked-questions in the sidebar |
| Font Mode | branded |
branded (Neulis Sans) or inherit (your store's theme font) |
| Custom CSS | (empty) | Additional CSS for the badge and sidebar. Always takes priority over the plugin's own styles, so !important isn't needed |
The quickest way to restyle is to override the plugin's colour and shape settings in Custom CSS:
:root {
--loxa-v3-accent: #0a5c36; /* buttons and selected plan */
--loxa-v3-badge-bg: #f4f8f5; /* badge background */
--loxa-v3-radius-scale: 0; /* 0 = square corners, 1 = default, 3 = pill */
}
Developer
| Field | Default | Notes |
|---|---|---|
| Debug Mode | Off | Enables [Loxa] browser console logs for administrators, and server-side logging |
| Dummy Payload Mode | disabled |
Uses local test data instead of live API calls — addon, inclusive or hybrid_extension |
| Disable Main Flow | Off | Disables all automatic listeners; for fully custom JS integrations |
| Quote Cache | — | Clear cached quotes button. A quote is reused for 5 minutes for the same product and price; clear it to see a change made in Loxa straight away |
Developer hooks
For developers adapting the plugin to a store. Add them in a small custom plugin or the theme's functions.php.
| Hook | Type | Use |
|---|---|---|
loxa_insurance_trust_proxy_headers |
filter (bool, default false) |
Return true if the store sits behind a CDN or load balancer that sets X-Forwarded-For, so the per-visitor quote limit sees each shopper's own address. Leave off otherwise — the header can be faked |
loxa_insurance_rate_limit |
filter (int, default 30) |
Calls to Loxa allowed per minute from one visitor |
loxa_insurance_store_rate_limit |
filter (int, default 300) |
Calls to Loxa allowed per minute across the store |
loxa_insurance_configurable_product_types |
filter (string[]) | Product types priced from the options the shopper picks (default composite, bundle, mix-and-match) |
loxa_insurance_offered_option_ids |
filter (int[]|null, WC_Product) |
For a configurator plugin the plugin doesn't recognise: return the product IDs the product offers as options. Until then, option IDs sent for it are ignored |
loxa_insurance_composite_price |
filter (float, WC_Product, option IDs, config) |
Replace the computed configurator price, for pricing rules the plugin can't see |
loxa_insurance_order_submission_failed |
action (order ID, reason) | Fires when an order couldn't be sent for policy creation — wire it into your alerting |
Troubleshooting
Insurance badges are not appearing on product pages
Check the following:
- Plugin is enabled — go to WooCommerce > Settings > Integration > Loxa Insurance and confirm Enable is checked.
- API key and environment are set — the API key must be valid for the selected Environment (Test or Live).
- Product is insurable — the Loxa API must return
insurable: trueandactive: truefor the product. Enable Debug Mode to see[Loxa]console logs. - A variation is selected — for variable products, cover is quoted once a variation is chosen, at that variation's price.
- Anchor elements exist — the plugin injects anchors via the
woocommerce_single_product_summaryhook. If your theme doesn't fire this hook, set the anchor selectors or add the anchors manually:<span id="loxa-woocommerce-inclusive-anchor" data-loxa-woocommerce-anchor="inclusive"></span> <span id="loxa-woocommerce-addon-anchor" data-loxa-woocommerce-anchor="addon"></span> - Product is not excluded — check that the product's categories or tags don't match the Exclusion Tags setting.
- Product has a SKU — products are quoted by SKU, so a product (or, for a variable product, the product and its variations) needs one. Set it under Product data > Inventory > SKU.
- Recent changes in Loxa — a quote is reused for 5 minutes, so a change made in Loxa (for example a product's category) can take up to 5 minutes to show. To see it straight away, use Clear cached quotes under Developer in the plugin settings, then reload the product page.
\"We couldn't add product protection to this item\"
The product was added to the cart but its cover wasn't, because the quote couldn't be verified. This happens if the page was left open for more than 24 hours (quotes expire), or if the quote was changed in the browser. Refreshing the product page fetches a new quote — add the product with cover again.
If it happens on every attempt, check the Insurance Product ID in settings (generate the product if it's empty) and enable Debug Mode to look for [Loxa] errors.
Orders aren't reaching Loxa (Send Orders to Loxa)
Open the order and check its order notes — every attempt is recorded there.
- No Loxa note at all — check that Send Orders to Loxa is not Off, that the order contains insurance, and that the order has reached the chosen trigger (paid, or completed).
- "Retrying in N min" — Loxa couldn't be reached; the plugin will try again automatically.
- "NOT sent" — the order was rejected or ran out of retries. Fix the cause if the note gives one (e.g. no API key configured), then use Order actions > Send to Loxa (create policy), or contact Loxa support.
Orders are sent by WooCommerce's background task runner (WooCommerce > Status > Scheduled Actions, group loxa-insurance), which relies on site traffic or WP-Cron to run.
A customer ticked \"interested in product protection\" but wasn't emailed
Open the order and check its order notes:
- No Loxa note — the order hasn't been paid yet (bank transfer or cash on delivery orders are sent once you confirm payment).
- "none of the items … can be protected after purchase" — Loxa couldn't cover the item after purchase, so no email was sent.
- "not switched on for this store" — ask Loxa to enable post-purchase.
- "the email is turned off" — enable Product protection offer in WooCommerce > Settings > Emails, then use Order actions > Send post-purchase offer (Loxa).
- "the email to the customer could not be sent" — your store couldn't send email (see Your store must be able to send email). Fix your mail setup, then use Order actions > Send post-purchase offer (Loxa).
- "its link was not a secure (https) address" — contact Loxa support.
The tickbox doesn't appear on an item above the point-of-sale limit
- Post-Purchase Protection Offers is on (under Orders in the plugin settings).
- The Product protection offer email is enabled in WooCommerce > Settings > Emails.
- Loxa has enabled post-purchase for your store, and the item is within the plan's limit of indemnity.
- For a variable product, the expensive variation is selected — each variation is quoted at its own price.
Express checkout buttons (Google Pay, Apple Pay, PayPal) bypass insurance
Express checkout buttons on the product page initiate their own payment flow directly with the payment provider, bypassing the standard add-to-cart form. Insurance data is never submitted through these flows.
Options:
- Disable express checkout buttons on product pages — customers who add to cart normally will always be offered insurance
- Use the Buy Now Selector setting if the button submits through the product form
- Express checkout on the cart and checkout pages is unaffected since insurance is already in the cart
Insurance prices don't update when selecting a product variation
- Check the Variant Selector — if your theme uses custom dropdowns or swatches, you may need to set the CSS selector in settings.
- Adjust the Variant Delay — if prices flash or re-fetch too quickly, increase the debounce delay (e.g.
200). - Check the Variant ID Source — try switching between
auto,formandurlto match how your theme reports the selected variation.