PrestaShop Integration Guide
The Loxa PrestaShop module is a turnkey integration that handles insurance display, cart management, and order data persistence — no custom frontend or backend code required. Install the module, configure your API credentials in the back office, and Loxa Product Protection will appear on your product pages automatically.
You can see the module in action on our PrestaShop Test Store. All four insurance integration types are supported: Add-on, Inclusive, Hybrid Extension, and Hybrid Warranty. For details on what each type means, see the Generic Integration Guide.
Demo store access
The PrestaShop demo store is behind HTTP Basic Auth to keep it private. If you'd like access for evaluation, contact us at developers@loxacover.com.
The module supports both PrestaShop 1.7 and PrestaShop 8 from a single zip.
Requirements
| Requirement | Version |
|---|---|
| PrestaShop | 1.7.0 or 8.x |
| PHP | 7.2+ (PS 1.7) / 8.1+ (PS 8) |
| MySQL / MariaDB | 5.6+ / 10.x |
The module installs cleanly on stock Classic theme installations and supports custom themes via configurable selectors (see Theme Compatibility below).
Installation
Upload the module ZIP through the PrestaShop back office:
- Go to Modules > Module Manager.
- Click Upload a module at the top right of the page.
- Drag the ZIP file provided by Loxa onto the upload area, or click and select it.
- Wait for the green confirmation. The module installs itself and creates the database tables it needs.
- Click Configure on the Loxa Insurance row.
Alternatively, extract the ZIP into your /modules/ directory and click Install from the Module Manager.
Updates
The module supports in-back-office automatic updates. Paste a GitHub Personal Access Token (with read access to the Loxa repo) into the configuration page and the Module Updates panel will check GitHub for new releases every 30 minutes. Click Apply update to upgrade in place — your configuration, the insurance product, and the HMAC secret all survive the upgrade.
Schema migrations and hook re-registrations run automatically as part of every update. A self-heal also fires on every back-office page load: it checks the live database schema against what the installed code expects and applies any missing migrations idempotently. This runs independently of the recorded module version, so however the new files reached the server — Module Manager upload, in-back-office updater, FTP/SFTP, cPanel file manager, rsync, a deployment pipeline — the database is brought into line on the next admin page view with no manual intervention.
Generate the Insurance Product
The module uses a hidden virtual product (loxa-insurance) as the line item template for insurance in the cart. You need to generate this product once after installation.
- On the module's configuration page, click Generate Insurance Product (the button is at the top of the page).
- The module creates a virtual product with reference
loxa-insurance, base price0.00, hidden from the catalogue. - The actual premium is set dynamically per cart line via PrestaShop's
SpecificPricemechanism when insurance is added.
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.
Catalogue artefacts you'll see
Once insurance starts being added to carts, the module creates two things in your catalogue:
- A
Loxa Planattribute group with one attribute per plan code seen in production - Combinations of the
loxa-insurancevirtual product, one per(plan code, insured product)pair, with references shapedloxa-plan-<CODE>-p<id>-pa<id>
These are intentional — they're how the module gives each insured parent product its own cart line. The loxa-insurance product is hidden from the catalogue, so customers never see the attribute group or the combinations. Don't delete them manually; they're managed by the module.
Configure API Credentials
On the module's configuration page, fill in the following fields under API Configuration:
| Field | Description |
|---|---|
| Enable | Switch to "Yes" once the rest is set |
| API Key | Your API key provided by Loxa (rendered as a password field; leave empty to keep the existing value) |
| API Base URL | The Loxa API base URL, e.g. https://api.loxacover.com/test/2026-02 |
| API Endpoint | The insurance information endpoint, e.g. /products/insurance-information |
| Analytics Base URL | Analytics endpoint base URL (optional) |
| Analytics Key | Analytics API key (optional, password field) |
| GitHub Token | Personal access token (Contents: Read on the Loxa repo) for in-back-office updates (optional) |
HMAC secret is auto-generated
The HMAC secret used to sign premiums is generated automatically when the module is installed and never has to be set manually. You'll see it on the configuration page as a masked panel with a Regenerate HMAC Secret button — only use that if you have a specific reason to rotate it (e.g. a suspected leak). Rotating invalidates any in-flight signed quotes that haven't been added to a cart yet.
Password fields don't echo back
API Key, Analytics Key, and GitHub Token render as password inputs. After saving, the fields display as empty — this is intentional, the value is not written back into the page HTML for security. Leave a password field empty to keep its current value; type a new value to change it. A "(saved)" suffix appears next to the field label when a value is set.
How It Works
Once installed and configured, the module handles the full insurance lifecycle automatically:
┌─────────────────────────────────────────────────────────────────────┐
│ PRODUCT PAGE (browser) │
│ │
│ 1. Page loads → PHP injects product data + settings as JSON │
│ 2. JS calls server-side proxy (/module/loxainsurance/price) │
│ 3. Proxy resolves price server-side from product id (no client │
│ trust), adds API key, forwards to Loxa API │
│ 4. Proxy attaches HMAC signatures to each plan in the response │
│ 5. JS renders insurance badge and sidebar from API data │
│ 6. Customer selects a plan → JS injects insurance data into form │
│ 7. Customer clicks "Add to Cart" │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ SERVER (PrestaShop) │
│ │
│ 8. Cart hook validates HMAC signature on the premium │
│ 9. Cart hook resolves a per-(plan, parent product) combination │
│ of the insurance product and adds it as its own cart line │
│ 10. Insurance JSON stored in custom table (loxa_insurance_cart), │
│ keyed by (id_cart, id_product_parent, id_product_attribute) │
│ 11. Premium applied via SpecificPrice scoped to the combination │
│ so distinct insured products don't overwrite each other │
│ 12. Existing insurance for the SAME parent product is replaced; │
│ different parents in the same cart coexist on separate lines │
│ 13. Insurance quantity synced with parent product quantity │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ CHECKOUT → ORDER │
│ │
│ 14. actionValidateOrder hook copies insurance to │
│ loxa_insurance_order (linked to id_order_detail) │
│ 15. Insurance also surfaces on order_detail rows as Smarty meta │
│ so it appears in standard order screens / invoices │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ ORDER PROCESSING │
│ │
│ 16. Loxa pulls orders via the PrestaShop Webservice API │
│ 17. Loxa processes policies from the insurance data │
│ 18. Customer receives welcome email from Loxa │
└─────────────────────────────────────────────────────────────────────┘
What the Module Handles Automatically
You do not need to build any of the following — the module takes care of it:
- Badge rendering — all four integration types (addon, inclusive, hybrid extension, hybrid warranty) with Loxa-branded badges and styling
- Insurance sidebar — terms, legal disclaimers, plan selection, and the "Details" / "What's included?" overlay
- Combination re-pricing — when a customer selects a different combination (size, colour, etc.), the module re-fetches insurance pricing at the new price point
- Server-side price authority — the price used for each insurance quote is resolved server-side from the product database; client-side price tampering is impossible
- HMAC price verification — premiums are signed server-side and verified on add-to-cart to prevent price tampering
- Cart line item management — each insured product gets its own insurance cart line, scoped by a per-(plan, parent product) combination so distinct policies coexist with their own prices. Adding a second plan for the same parent replaces the first; removing an insured product automatically removes only its own linked insurance, never a sibling's
- Multi-product carts — a customer can insure several different products in one basket. Each insurance line tracks its own plan, sum insured, and parent SKU and survives independently of the others
- Quantity synchronisation — insurance quantity is locked and automatically synced with the parent product quantity
- Voucher exclusion — insurance line items are excluded from cart-rule discounts
- Second-chance mechanism — optionally intercepts the add-to-cart click if the customer hasn't selected insurance and shows the sidebar as a reminder (configurable in settings)
- Quote-to-order persistence — insurance data follows the order through PrestaShop's checkout into both
loxa_insurance_orderand visible meta on the order detail rows - Compliance — opt-out flows for inclusive insurance are built in per Compliance Rules
- Catalogue visibility — the insurance virtual product is hidden from the shop catalogue and search results
- In-back-office updates — when a GitHub Token is configured, new releases surface as an "Update available" banner with a one-click apply
- Self-healing upgrades — every back-office page load checks the database schema against what the installed code expects and applies any missing migrations idempotently. This runs independently of the recorded module version, so however the files reached the server (Module Manager upload, the in-back-office updater, FTP/SFTP, file manager, rsync, a deployment pipeline), the database converges to the correct shape without manual intervention
Order Processing
Unlike a custom integration where you would POST orders to the Loxa Orders API, the PrestaShop module works the other way around — Loxa pulls orders from your PrestaShop Webservice.
How it works
- When a customer completes checkout with insurance, the
actionValidateOrderhook records the plan metadata for each insurance line in the customloxa_insurance_ordertable. - Loxa periodically calls
GET /api/loxa_insurance_orders?display=fullon your PrestaShop Webservice. This single endpoint returns every field needed to issue a policy — order status, customer, delivery address, line items, and plan data — denormalised into one response. - Loxa processes the insurance policies and the customer receives their welcome email and policy documents.
What you need to provide
To enable Loxa to pull orders, you need to enable the PrestaShop Webservice and create an API key:
- Go to Advanced Parameters > Webservice.
- Switch Enable PrestaShop's webservice to Yes and save.
- Click Add new webservice key.
- Generate a key (or paste your own; 32+ characters of mixed case + digits).
- Set Key description to "Loxa".
- Set Status to Enabled.
- Under Permissions, grant GET (View) on only one resource:
loxa_insurance_orders
- Save.
- Share the generated key with Loxa:
| Credential | Description |
|---|---|
| Webservice Key | 32+ character key, used as the HTTP Basic Auth username with an empty password |
| Webservice URL | Your store base URL, e.g. https://store.example.com/api/ |
Single-resource access by design
From module 1.1.6 onwards, granting GET on loxa_insurance_orders is sufficient. Do not also grant access to orders, customers, addresses, or products — the denormalised endpoint exposes only the fields needed to issue a policy and is the audited surface for PII access. Wider permissions broaden the data exposure unnecessarily and are not required by the integration.
Keep these credentials secure
The webservice key grants read access to insured orders. Share it with Loxa through a secure channel — never send it over plain email or commit it to version control. Always serve the Webservice over HTTPS — basic auth credentials over plain HTTP are recoverable from any intermediate proxy.
You do not need to POST orders to Loxa
The PrestaShop module does not require you to call the POST /orders endpoint. Loxa reads orders directly from your Webservice. There is no additional backend development required on your side.
Webservice response shape
GET /api/loxa_insurance_orders/{id}?display=full returns one record per insured line item, with the order context, customer, delivery address, and plan denormalised onto the row:
Example response
{
"loxa_insurance_order": {
"id": 1024,
"id_order": 4521,
"id_order_detail": 12053,
"id_order_detail_parent": 12052,
"date_add": "2026-04-27 11:42:18",
"order_reference": "XXKVDPZNB",
"order_status_id": 5,
"order_status": "Delivered",
"order_total_paid": 1401.98,
"order_currency": "GBP",
"order_date": "2026-04-27 11:41:55",
"customer_email": "j***@example.com",
"customer_firstname": "Jane",
"customer_lastname": "Doe",
"delivery_address1": "12 Example Street",
"delivery_address2": "",
"delivery_city": "London",
"delivery_postcode": "EC1A 1BB",
"delivery_country": "GB",
"delivery_phone": "07000 000000",
"insurance_line": "{\"id_order_detail\":12053,\"sku\":\"loxa-insurance\",\"name\":\"Product Protection\",\"quantity\":1,\"unit_price\":101.99,\"line_total\":101.99}",
"parent_line": "{\"id_order_detail\":12052,\"sku\":\"sofa-3-seater\",\"name\":\"3 Seater Chesterfield Sofa\",\"quantity\":1,\"unit_price\":1299.99,\"line_total\":1299.99}",
"insurance_plan": "{\"code\":\"LDF5-20260119-23\",\"name\":\"Product Protection\",\"term\":\"5\",\"premium_raw\":\"101.99\",\"sum_insured\":\"1299.99\",\"signature\":\"a1b2c3d4\",\"parent_sku\":\"sofa-3-seater\"}"
}
}
| Field group | Fields | Notes |
|---|---|---|
| Order context | order_reference, order_status_id, order_status, order_total_paid, order_currency, order_date |
Computed live from ps_orders — always reflects current order state |
| Customer | customer_email, customer_firstname, customer_lastname |
PII; minimised — no DOB, no marketing prefs, no customer ID |
| Delivery | delivery_address1, delivery_address2, delivery_city, delivery_postcode, delivery_country, delivery_phone |
PII; invoice address is not exposed (delivery address is what policies are issued against) |
| Line items | insurance_line, parent_line |
Both returned as JSON-encoded strings ({id_order_detail, sku, name, quantity, unit_price, line_total}) |
| Plan | insurance_plan |
JSON-encoded string with code, term, premium_raw, sum_insured, signature, parent_sku |
The id_order_detail_parent field links the insurance line back to the product line within the same order, so Loxa can match insurance to its parent product unambiguously even when an order contains several insured items.
Cancellations
Loxa handles cancellation tracking once orders are pulled. If you need to notify Loxa of cancellations outside of the standard flow, you can use the Cancellations endpoint directly.
Data Protection (GDPR)
The loxa_insurance_orders endpoint is the only surface through which Loxa accesses customer PII for the purposes of issuing a policy. The integration is designed around the GDPR data-minimisation principle.
Roles
| Party | Role |
|---|---|
| Retailer (you) | Data controller for your customer data |
| Loxa | Data processor for the PII received via the Webservice — used solely to issue, administer, and pay claims on the policy purchased by the customer |
The lawful basis for the data transfer is performance of contract (Art. 6(1)(b) UK GDPR / EU GDPR) — the customer has purchased an insurance policy and the data is necessary to provide it.
What is exposed
Only the minimum fields required to issue and administer a policy are returned by the Webservice:
- Customer email + first/last name (policy delivery and identification)
- Delivery address (territorial validity, fraud screening)
- Delivery phone (claims contact)
The following are not exposed by loxa_insurance_orders:
- Invoice address (delivery is sufficient)
- Date of birth, marketing preferences, password hashes
- Customer ID, customer group memberships, internal CRM notes
- Cart history, browsing history, other order history
What we do not store twice
The PII fields are computed live from your PrestaShop database on each Webservice read — they are not snapshotted into a Loxa table. This means:
- A customer's right-to-erasure request applied in your PrestaShop install propagates to subsequent reads with no action required by Loxa.
- Address corrections in PrestaShop are reflected immediately.
- The data is in your database exactly once, where your existing data-protection processes apply.
Audit trail
Every Webservice read against loxa_insurance_orders is recorded in the ps_loxa_insurance_access_log table on your PrestaShop install. Each row captures:
- The webservice account ID that made the call
- The source IP
- The number of records returned
- The timestamp
No PII is stored in the log.
Transport security
The Webservice must be served over HTTPS in production. Basic auth credentials sent over plain HTTP are recoverable from any intermediate proxy. If you can, restrict access to the /api/ path to known Loxa source IPs at your CDN or firewall layer.
Theme Compatibility
The module is designed to work with standard PrestaShop themes. It injects anchor elements into the product page using PrestaShop's displayProductAdditionalInfo hook and renders the sidebar in a hidden Smarty template loaded on every product page.
| Theme | Status | Notes |
|---|---|---|
| Classic (default PS theme) | Standard PrestaShop hooks are present | |
| Hummingbird (PS 8 default) | Hooks are present and structure matches | |
| Custom themes | See below |
For custom themes that restructure the product page or use non-standard selectors for the add-to-cart button, quantity input, or combination pickers, you can configure the relevant CSS selectors in the module settings.
If your theme does not render the standard displayProductAdditionalInfo hook, you can manually add the anchor elements to your templates/catalog/product.tpl:
<span id="loxa-shopify-inclusive-anchor" data-loxa-shopify-anchor="inclusive"></span>
<span id="loxa-shopify-addon-anchor" data-loxa-shopify-anchor="addon"></span>
The loxa-shopify-* prefix is intentional — these IDs are shared across all our platform modules so a single stylesheet covers everything.
Admin Configuration Reference
All settings live on the Loxa Insurance module's configuration page, reachable from Modules > Module Manager > Loxa Insurance > Configure.
Product Page Settings
| Field | Default | Notes |
|---|---|---|
| Add to Cart Selector | .add-to-cart-or-refresh button[data-button-action="add-to-cart"] |
CSS selector for the ATC button |
| Variant Selector | (empty) | Optional CSS selector for custom combination pickers |
| Quantity Selector | #quantity_wanted |
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 override for where the add-on badge attaches (defaults to auto-placement above ATC) |
| Inclusive Anchor Selector | (empty) | Optional override for where the inclusive badge attaches |
Behaviour
| Field | Default | Notes |
|---|---|---|
| Sidebar Position | right |
left or right |
| Second Chance | Off | Shows sidebar if customer clicks ATC without selecting insurance |
| Wait For Variant Delay | 300 |
Debounce in ms before re-fetching insurance on combination change |
| Variant ID Source | auto |
How to detect the selected combination; auto covers most themes |
| Exclusion Tags | (empty) | Comma-separated category or tag names to exclude from insurance |
| VAT Excluded | Off | Enable if catalogue prices are ex-VAT; applies the configured rate for insurance pricing |
| Category Override | Off | Passes a category override to the Loxa API based on product tags prefixed with loxa-. Must be agreed with Loxa before use. |
Appearance
| Field | Default | Notes |
|---|---|---|
| Theme Mode | light |
light, dark, or midnight |
| Font Mode | branded |
branded (Neulis Sans) or inherit (your theme's font) |
| Custom CSS | (empty) | Additional CSS applied to the insurance badge and sidebar |
Developer
| Field | Default | Notes |
|---|---|---|
| Debug Mode | Off | Enables [Loxa] browser console logs |
| Dummy Payload Mode | disabled |
Uses local test data instead of live API calls — options: addon, inclusive, hybrid_warranty, hybrid_extension |
| Disable Main Flow | Off | Disables all automatic listeners; for fully custom JS integrations |
Updates
| Field | Default | Notes |
|---|---|---|
| GitHub Token | (empty) | Fine-grained PAT with Contents: Read on the Loxa repo. When set, the Module Updates panel checks for new releases every 30 minutes and offers in-place updates. |
Troubleshooting
Insurance badges are not appearing on product pages
Check the following:
- Module is enabled — Modules > Module Manager > Loxa Insurance > Configure, confirm Enable is set to Yes.
- API credentials are configured — verify the API key and base URL are filled in (the API Key field shows "(saved)" next to its label when a value is set). The HMAC secret is auto-generated, so it should always be present unless something has gone wrong.
- Product is insurable — the Loxa API must return
insurable: trueandactive: truefor the product. Enable Debug Mode to see[Loxa]console logs. - Anchor elements exist — the module injects anchors via the
displayProductAdditionalInfohook. If your theme doesn't fire this hook, add the anchors manually toproduct.tpl:<span id="loxa-shopify-inclusive-anchor" data-loxa-shopify-anchor="inclusive"></span> <span id="loxa-shopify-addon-anchor" data-loxa-shopify-anchor="addon"></span> - Product is not excluded — check that the product's categories or tags don't match the Exclusion Tags setting.
- Smarty cache is fresh — Advanced Parameters > Performance > Clear cache. PrestaShop aggressively caches Smarty templates and JS settings.
Insurance is not being added to the cart
Check the following:
- Insurance product exists — the configuration page shows the Insurance Product ID at the top. If empty, click Generate Insurance Product.
- HMAC secret is present — the secret is auto-generated on install. The HMAC panel on the configuration page shows a masked preview when one is set. If the panel says no secret is configured (rare), click Regenerate HMAC Secret to create one.
- Check the PrestaShop log — Advanced Parameters > Logs. Search for
Loxato see verification failures. - Browser console — enable Debug Mode and watch for
[Loxa]errors when adding to cart.
Insurance prices don't update when selecting a combination
- Check the Variant Selector — if your theme uses custom dropdowns or swatches, you may need to set a CSS selector in settings.
- Adjust the Wait For Variant Delay — if prices flash or re-fetch too quickly, increase the debounce (e.g.
500). - Check the Variant ID Source — try
auto,form, orurlto match how your theme reports the selected combination.
Express checkout buttons (PayPal, Klarna, Apple Pay) 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 config 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
Module update through the back office failed
- Check the GitHub Token — verify it's still valid and has Contents: Read on the
boltcover/loxa-prestashop-insurancerepo. Tokens expire by default. - Check write permissions on /modules — the user PrestaShop's PHP runs as (typically
www-data) needs write access to/modules/loxainsuranceand the parent/modulesdirectory for the in-place swap to succeed. - Manual fallback — if the in-back-office update fails, download the latest ZIP from the link above and upload it via Module Manager, or extract it directly into
/modules/loxainsurance/. The module's self-heal runs on the next back-office page load and applies any pending upgrade scripts, so manual deployments converge to the same state as the in-back-office updater. - Configuration is preserved — uninstalling and reinstalling the module does not wipe your API key, HMAC secret, or generated insurance product. They live in
ps_configurationindependently of the module record.
How do I roll back to a previous version?
Download an older release zip from the Loxa repository (or ask your contact at Loxa for the specific version), then upload via Module Manager. PrestaShop will install older files in place. Note that downgrades skip upgrade scripts; if a previous version's schema differs significantly from the current one, contact Loxa before downgrading.