Skip to content

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

Download Module ZIP

Upload the module ZIP through the PrestaShop back office:

  1. Go to Modules > Module Manager.
  2. Click Upload a module at the top right of the page.
  3. Drag the ZIP file provided by Loxa onto the upload area, or click and select it.
  4. Wait for the green confirmation. The module installs itself and creates the database tables it needs.
  5. 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.

  1. On the module's configuration page, click Generate Insurance Product (the button is at the top of the page).
  2. The module creates a virtual product with reference loxa-insurance, base price 0.00, hidden from the catalogue.
  3. The actual premium is set dynamically per cart line via PrestaShop's SpecificPrice mechanism 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 Plan attribute group with one attribute per plan code seen in production
  • Combinations of the loxa-insurance virtual product, one per (plan code, insured product) pair, with references shaped loxa-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_order and 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

  1. When a customer completes checkout with insurance, the actionValidateOrder hook records the plan metadata for each insurance line in the custom loxa_insurance_order table.
  2. Loxa periodically calls GET /api/loxa_insurance_orders?display=full on 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.
  3. 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:

  1. Go to Advanced Parameters > Webservice.
  2. Switch Enable PrestaShop's webservice to Yes and save.
  3. Click Add new webservice key.
  4. Generate a key (or paste your own; 32+ characters of mixed case + digits).
  5. Set Key description to "Loxa".
  6. Set Status to Enabled.
  7. Under Permissions, grant GET (View) on only one resource:
    • loxa_insurance_orders
  8. Save.
  9. 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) ✅ Works out of the box Standard PrestaShop hooks are present
Hummingbird (PS 8 default) ✅ Works out of the box Hooks are present and structure matches
Custom themes ⚠ May need config 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:

  1. Module is enabled — Modules > Module Manager > Loxa Insurance > Configure, confirm Enable is set to Yes.
  2. 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.
  3. Product is insurable — the Loxa API must return insurable: true and active: true for the product. Enable Debug Mode to see [Loxa] console logs.
  4. Anchor elements exist — the module injects anchors via the displayProductAdditionalInfo hook. If your theme doesn't fire this hook, add the anchors manually to 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>
    
  5. Product is not excluded — check that the product's categories or tags don't match the Exclusion Tags setting.
  6. 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:

  1. Insurance product exists — the configuration page shows the Insurance Product ID at the top. If empty, click Generate Insurance Product.
  2. 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.
  3. Check the PrestaShop log — Advanced Parameters > Logs. Search for Loxa to see verification failures.
  4. Browser console — enable Debug Mode and watch for [Loxa] errors when adding to cart.
Insurance prices don't update when selecting a combination
  1. Check the Variant Selector — if your theme uses custom dropdowns or swatches, you may need to set a CSS selector in settings.
  2. Adjust the Wait For Variant Delay — if prices flash or re-fetch too quickly, increase the debounce (e.g. 500).
  3. Check the Variant ID Source — try auto, form, or url to 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
  1. Check the GitHub Token — verify it's still valid and has Contents: Read on the boltcover/loxa-prestashop-insurance repo. Tokens expire by default.
  2. Check write permissions on /modules — the user PrestaShop's PHP runs as (typically www-data) needs write access to /modules/loxainsurance and the parent /modules directory for the in-place swap to succeed.
  3. 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.
  4. Configuration is preserved — uninstalling and reinstalling the module does not wipe your API key, HMAC secret, or generated insurance product. They live in ps_configuration independently 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.