Official Documentation
CoverMyOrder
Customer opt-in shipping protection for WooCommerce. Collect a small fee at checkout, run an automated claims pipeline, resolve by refund or reship, and keep 100% of the premium — no SaaS round-trip, no per-claim fees, no data leaving your database.
Perfect for
- High-value orders
- International shipping
- Fragile & breakable goods
- Dropshipping & print-on-demand
- Subscription boxes
- Multi-carrier WooCommerce stores
Overview
Two independent plugins that install and activate side by side, matching the pattern of a WooCommerce extension and its add-on: the free plugin never requires Pro, and Pro never replaces or modifies the free plugin's files.
Protection
The row created at checkout when a customer opts in — the premium paid, the coverage cap, and the plan snapshot at that moment.
Claim
A customer's request against one protected order — one click, no manual amount entry, routed to auto-decision or the operator queue.
Plan
The pricing and coverage rules a protection is quoted from — one flat-fee plan on free, unlimited priced plans on Pro.
Reserve
The running ledger of premium collected vs. claims paid out — your loss ratio at a glance.
What happens on a protected order
- Customer opts in at checkout
A cart/checkout toggle (classic and Blocks-aware) lets the customer add protection before paying. The premium is added as a fee line on the order, so it flows through your existing tax and payment configuration unchanged.
- A Protection record is created
At payment time, the plugin captures the premium, the coverage cap, a snapshot of the plan they picked, and the coverage window. The snapshot matters: editing a plan later never retroactively changes what an already-protected order was sold.
- Confirmation is surfaced
A branded card appears on the thank-you page and in the order email so the customer knows the order is covered, with a link into the claim portal.
- The customer files a claim if something goes wrong
Through a self-serve portal — one click per protected order, no manual amount entry. Photos, video and PDFs attach as evidence.
- The claim is decided
On Pro, simple claims can auto-decide through a visual rule engine. Everything else — and everything on free — routes to the operator queue for manual review.
- Approved claims resolve
Either as a native WooCommerce refund, or — on Pro — as a reship: a duplicate $0 order in processing status that the merchant fulfils again.
Throughout, the reserve ledger tracks every unit of currency collected and paid out, so the loss ratio is always one glance away.
What CoverMyOrder is not
It is not an insurance policy, and it does not underwrite anything. The plugin is the software that lets you operate a shipping protection programme: you collect the premium, you hold the reserve, you decide the claims, and you carry the risk. Whether you are permitted to sell such a product, and under what terms, depends on the law where you trade — that question is outside the plugin's scope and is worth putting to a professional before launch.
Requirements
Minimum supported versions. Anything older is untested rather than actively blocked, but is not supported.
| Component | Minimum | Notes |
|---|---|---|
| WordPress | 6.3+ | Uses the Blocks integration API for the Cart/Checkout Block toggle. |
| PHP | 7.4+ | Typed properties and arrow functions are used throughout the domain layer. |
| WooCommerce | 8.0+ | Required for the Cart and Checkout Blocks integration surface. |
| HPOS | Compatible | All order reads and writes go through the WooCommerce CRUD layer, so High Performance Order Storage is supported rather than merely tolerated. |
| MySQL / MariaDB | InnoDB | The plugin creates its own indexed tables; the storage engine must support foreign-key-shaped access patterns and transactions. |
| Action Scheduler | Bundled with Woo | Used as the background queue for deferred work. |
Installation
Free first, then Pro. Installing Pro never touches the free plugin's files or database rows.
Free plugin
- Plugins → Add New
Search “CoverMyOrder”, click Install, then Activate. Or upload
covermyorder-1.8.0.zipdirectly. - Run the setup wizard
Appears automatically on first activation — pick a plan, enable the badge, configure tracking.
Premium add-on Pro
- Free plugin must already be active
Pro checks for it on load and shows an admin notice with a link to install or activate it if it's missing. Pro will not boot without it.
- Upload
covermyorder-pro-1.8.0.zipPlugins → Add New → Upload Plugin, or drop the unzipped folder into
wp-content/plugins/covermyorder-pro/. - Activate and enter your licence key
Every Pro gate flips on immediately once a licence is active — there is no separate configuration step and nothing to migrate.
Updating
Update the free plugin first, then Pro. The two are versioned together and a Pro release always targets the free release of the same version number. Running Pro 1.8.0 against free 1.7.x is unsupported: Pro hooks extension points that may not exist in the older core, and will surface an admin notice rather than fail silently.
Uninstalling
A Keep data on uninstall toggle in Settings → Data & privacy controls whether protections, claims, and ledger history survive plugin removal. It defaults to preserve, so accidental deactivation never silently deletes claims history.
Getting started
The setup wizard runs once, automatically, right after activation. Three questions, then a test order to prove the loop works end to end.
The wizard
- Pick a plan
Name it, set the flat fee, set the coverage cap. This becomes your one free-tier plan (see Plans & pricing).
- Enable the badge
The “Protected by CoverMyOrder” trust badge, shown on cart, checkout and thank-you.
- Configure tracking
Optional. Connect an AfterShip webhook for automatic carrier tracking-event ingestion.
Prove the loop works
Before you announce anything to customers, run one order all the way through. It takes about five minutes and it is the only way to know your gateway, your emails and your refund path all behave.
- Place a test order with protection opted in
Use a real gateway in test mode rather than Cash on Delivery — you want to exercise the refund path, and COD cannot refund.
- Confirm the thank-you card and the order email
Both should show the order is covered. If the email does not, the usual cause is a caching or transactional-email plugin intercepting the WooCommerce mailer.
- Check the order in wp-admin
The premium should appear as a fee line on the order, and a Protection row should exist under CoverMyOrder → Claims → the order.
- File a test claim
Through
[covermyorder_portal]or My Account → Protection. Attach a photo so you exercise the evidence upload path too. - Approve and resolve it
Resolve as a refund and confirm the money actually leaves the gateway. Then check the Reserve ledger: you should see the premium in, and the payout out, with a running balance.
Plans & pricing
A plan is the pricing and coverage rule a protection is quoted from. Free ships exactly one; Pro turns the screen into a card list of up to twelve.
Free: one plan
A single form with three fields: a name, a flat fee, and a fixed coverage cap. That is the complete free-tier surface. There is no coverage-model choice, because coverage is always a fixed cap — there is nothing to choose between. There is no percentage-pricing option either.
Pro: up to twelve plans Pro
Pro replaces the single form entirely with a card-per-plan list. Each card is a self-contained mini-editor. Once Pro's card list is active, the old single-plan form hides itself — the card list is the only Plans UI you will see.
- A drag handle plus up/down buttons to reorder — the order here is the order customers see at checkout.
- A segmented control for price: flat fee, or percentage of the order.
- A segmented control for coverage: fixed amount, 100% of order, or multiplier.
- A native colour swatch setting that plan's accent, used on its card, its checkout chip, and the customer-facing badge.
- An Active toggle — switching a plan off dims its card and swaps its checkout preview for a “won't appear at checkout” note, without deleting it.
- A star to mark the default plan, pre-selected for customers.
- A live checkout preview chip, tinted with the plan's own colour, showing exactly what customers will see as you edit.
Pricing models
| Model | Tier | Behaviour |
|---|---|---|
| Flat fee | Free | The same premium on every order, regardless of cart value. |
| Percentage of order | Pro | The premium scales with the order subtotal. Supplied by a PercentageStrategy that Pro registers through covermyorder/pricing/strategy_for_model. |
Coverage models
| Model | Tier | Payout ceiling for a claim |
|---|---|---|
| Fixed amount | Free | A flat cap, the same on every order. The only model available in free. |
| 100% of order | Pro | The order total itself becomes the ceiling. |
| Multiplier | Pro | The ceiling is a multiple of the premium paid. |
Category price overrides Pro
Charge more or less when a cart contains particular product categories — higher for fragile glassware, lower for a category that never goes missing. The pricing engine that applies overrides ships in the free plugin; what Pro adds is the only UI that writes the option.
Global coverage cap Pro
One store-wide payout ceiling that applies underneath every plan's own cap. If a plan would pay out £500 but the global cap is £300, the claim pays £300. It exists so a mispriced plan cannot bankrupt the reserve.
Fallback plans
If a checkout requests a plan id that no longer resolves — deleted, deactivated, or a stale page cache — the pricing layer asks covermyorder/pricing/fallback_plan_id for a substitute rather than failing the checkout. Deactivating a plan mid-session is therefore safe: in-flight carts fall back instead of erroring.
Admin guide
wp-admin → CoverMyOrder. Screens marked Pro only appear once the add-on is active and licensed.
Dashboard
KPIs (fees collected, active claims, reserve balance, loss ratio), sparkline charts, and a traffic-light health indicator. A matching “CoverMyOrder — At a Glance” widget is added to the default wp-admin home screen, so the numbers are visible without navigating anywhere.
Claims
A native WP_List_Table queue with status filters and an overdue-SLA column. Claim detail shows the evidence gallery, a customer risk profile sidebar, the carrier tracking timeline, and approve / deny / resolve actions with a full activity log.
Pro adds bulk queue actions, a reship resolution option alongside refund, a richer risk profile (lifetime order history), and auto-claim creation straight from a carrier webhook.
Plans
Covered in full under Plans & pricing. In short: one form in free, a twelve-card list in Pro.
Rules Pro
A visual rule builder with composable conditions and auto-approve / auto-deny actions, so simple claims never wait on an operator. Anything a rule does not match falls through to the manual queue — rules narrow the queue, they do not replace it.
Branding
Free: two colour presets (Indigo, Trust Green) and editable cart-toggle copy — title, description, opt-in and opt-out labels, thank-you text — with a live badge preview. The trust badge itself is mandatory-on in free, with a hardcoded title and description.
Pro adds five more presets plus a custom hex picker, a custom badge logo, per-surface placement control (or hiding the badge entirely), and agency white-labelling: a custom name in the admin menu, the email footers, and the customer portal.
Reserve
A paginated ledger of every premium collected and every claim paid out, with a running balance — the same number the Dashboard's loss-ratio KPI is built from. See Reserve & ledger.
Settings
Free ships three cards:
| Card | What it controls |
|---|---|
| Coverage policy | Pricing strategy and its parameters. |
| Tracking webhook | The inbound AfterShip secret used to authenticate carrier tracking events. |
| Data & privacy | The preserve-on-uninstall toggle. |
Pro injects two more sections onto this same page: per-category pricing overrides and the global coverage cap. Both are described under Plans & pricing.
Webhooks Pro
Outbound, HMAC-signed claim-event delivery to Slack, Zapier, or any custom URL. See Webhooks for the payload and signature details.
Claims workflow
From the customer clicking “file a claim” to the money leaving your account — and the audit trail that records it.
The lifecycle
-
Submitted
The customer files from the portal — one click, evidence attached, no manual amount entry.
-
Auto-decided Pro
The rule engine gets first refusal. A matching rule auto-approves or auto-denies without an operator ever seeing the claim.
-
Under review
Everything a rule did not match — and everything on free — lands in the operator queue with an overdue-SLA column.
-
Approved or denied
The decision, with a reason, written to the claim activity log.
-
Resolved
The money actually moves, or the replacement actually ships. Approval and resolution are separate actions with separate log entries.
A claim submitted through the portal lands as submitted. On Pro, the rule engine gets first refusal: if a rule matches, the claim is auto-approved or auto-denied without an operator ever seeing it. Everything else — and everything on free — moves to under review in the operator queue.
An approved claim is not finished. It still has to be resolved: the money has to actually move, or the replacement has to actually ship. That distinction is why approval and resolution are separate actions with separate log entries.
Evidence
Photos, videos and PDFs attach to a claim as evidence. The default limit is 10 files at 10 MB each — the same in free and Pro. There is no built-in Pro override, but both limits are filterable:
add_filter( 'covermyorder/evidence/max_files_per_claim', fn() => 20 );
add_filter( 'covermyorder/evidence/max_bytes_per_file', fn() => 25 * MB_IN_BYTES );
Resolution paths
| Path | Tier | What happens |
|---|---|---|
| Refund | Free | A native WooCommerce refund against the original order, through your gateway. The amount is capped by the coverage model on the protection and, if set, by the global coverage cap. |
| Reship | Pro | A duplicate order is created at $0 in processing status, which you fulfil again exactly like any other order. The original order is left untouched. |
Risk and fraud signals
The claim detail screen carries a customer risk profile sidebar. Free shows a basic profile; Pro extends it with lifetime order history, and the rule engine can act on those signals directly — auto-denying, or simply flagging for a human.
Carrier tracking
With an AfterShip webhook configured, carrier tracking events are ingested automatically and shown as a timeline on the claim. On Pro, a tracking event that indicates a lost or damaged shipment can create the claim itself, with no customer action at all.
Reserve & ledger
The reserve is the number that tells you whether the programme is working. Everything else on the dashboard is decoration by comparison.
What the ledger records
Two kinds of row, in one append-only table, with a running balance:
| Row type | Created when | Effect on balance |
|---|---|---|
| Premium collected | A protected order is paid for. | Increases |
| Claim paid out | An approved claim is resolved. | Decreases |
Nothing is aggregated away and nothing is edited in place. Every entry ties back to a WooCommerce order, which is what lets you hand the ledger to an accountant and have the numbers survive the conversation.
Loss ratio
The single KPI worth watching: total paid out, divided by total collected. Below 1.0 the programme is profitable; above 1.0 it is subsidising your shipping losses out of margin. The Dashboard shows it as a traffic light so you notice the direction of travel before the balance does.
CSV export Pro
Claims, protections, and the full reserve ledger export to CSV for reconciliation against your books.
Customer portal
Everything a customer sees, from checkout through filing a claim.
Cart & checkout badge
The opt-in toggle and trust badge render on both classic checkout and Cart/Checkout Blocks.
Thank-you card
Confirms coverage right after purchase, with a link into the claim portal.
My Account → Protection
A native WooCommerce endpoint listing every protected order.
[covermyorder_portal]
A standalone shortcode and block version of the same portal, cookie-identified — no password required.
Claim status emails
Branded HTML emails for every stage: submitted, approved, denied, resolved.
Evidence uploads
Photos, videos and PDFs attach to a claim as evidence.
Guest claims
The shortcode portal is cookie-identified, so a customer who checked out as a guest can still file and track a claim without creating an account. This matters more than it sounds: requiring a password at the moment someone is already annoyed that their parcel is missing is how you turn a claim into a chargeback.
Overriding the customer-facing views
Every template a customer sees can be overridden from your theme. See Templates.
Free vs Pro
The complete capability split, kept in sync with what the code actually gates — not what a feature list might imply.
| Capability | Free | Pro |
|---|---|---|
| Plans | 1, flat fee, fixed coverage cap | Up to 12, flat or percentage pricing, fixed / 100%-of-order / multiplier coverage, per-plan accent colour, drag-to-reorder |
| Category price overrides | Engine ships in core; no UI to configure it | Adds the Settings-page UI that writes the option |
| Global coverage cap | — | One store-wide payout ceiling under every plan's own cap |
| Rules | Manual review only | Visual rule builder, auto-approve / auto-deny |
| Branding | 2 presets, badge mandatory-on, hardcoded title/description | +5 presets, custom hex, custom logo, placement control, badge can be hidden, agency white-label |
| Claims | Bulk & single actions, risk profile | + Reship resolution, richer risk profile, auto-claim from carrier webhook |
| Analytics | Standard dashboard, top SKUs with claims | + Carrier-level loss ratio & payout analytics |
| Evidence per claim | 10 files @ 10 MB (filterable) | Same defaults today |
| REST API | Read-only | + Write access via API tokens |
| Integrations | — | Outbound webhooks, CSV export, SMS via Twilio, multi-store management |
How the gating actually works
There is no central “capabilities registry.” Free simply never implements the Pro behaviour, and covermyorder/license/is_pro plus a small set of action and filter hooks (covermyorder/plans/allow_multi, covermyorder/admin/settings/advanced_sections, and similar) let Pro extend or fully replace a screen when it is active. See License gating for the mechanism.
FAQ & troubleshooting
The questions that actually get asked, and the failures that actually happen.
Do I need both plugins, or does Pro replace the free one?
Both. Pro is an add-on, not a replacement — it requires the free plugin to be installed and active, and never modifies the free plugin's files.
What happens to my claims history if I deactivate or uninstall?
Deactivating never deletes anything. Uninstalling only deletes data if “Keep data on uninstall” in Settings → Data & privacy is turned off — and it defaults to preserve.
Can free stores offer more than one protection plan?
No. Free enforces exactly one plan: name, flat fee, fixed coverage cap. Multiple plans, percentage pricing, and coverage multipliers are Pro-only, via the card-based Plans screen.
Why don't I see a coverage-model choice on the free Plans screen?
Coverage is always a fixed cap in free — there is no dropdown because there is nothing to choose between. “100% of order” and “Multiplier” coverage only appear once Pro is active.
Where did the per-category pricing override screen go?
It lives on the Settings page, added by Pro — not on the Plans page. This is the single most commonly missed screen in the plugin.
What's the actual evidence upload limit?
10 files per claim, 10 MB each, by default — the same for free and Pro. Both numbers are filterable (covermyorder/evidence/max_files_per_claim, covermyorder/evidence/max_bytes_per_file).
My outbound webhook signature verification fails — which header is it?
X-CoverMyOrder-Signature (HMAC), alongside X-CoverMyOrder-Event and a User-Agent of CoverMyOrder-Pro/{version}. See Webhooks for the full payload shape. The most common cause of a failed check is verifying against a parsed body rather than the raw request body.
The protection toggle does not appear at checkout.
Three usual causes, in order of likelihood: the plan is switched off (Active toggle on its card); a page or fragment cache is serving a stale cart; or a checkout-customiser plugin is stripping the fee line. Test with caching disabled before anything else.
A claim was approved but no money moved.
Approval and resolution are separate steps. An approved claim still has to be resolved as a refund or a reship. If you resolved it as a refund and nothing left the gateway, the gateway does not support API refunds — issue the refund manually and mark the claim resolved.
Can I run this on a multisite network?
Each site keeps its own tables, plans and ledger. Multi-store management — managing claims across connected stores from one dashboard — is a Pro feature.
Architecture
A layered architecture, PSR-11 container, autowired, with a two-phase register() → boot() provider lifecycle. Each layer only calls downward.
Why the domain layer has no WordPress in it
Claim, Protection, Policy and Money are plain PHP objects. They do not call get_option(), they do not touch $wpdb, and they do not know WordPress exists. Everything that needs the outside world goes through a repository or a service. The practical payoff is that pricing and coverage logic is unit-testable without booting WordPress at all — which is the only reason the money maths can be trusted.
Provider lifecycle
Service providers run in two phases. register() binds things into the container and must not assume anything else exists yet. boot() runs once everything is registered, and is where hooks are added. Pro registers its own providers inside covermyorder/pro/boot, which fires only after the free plugin has confirmed an active licence.
Data model
Ten indexed custom InnoDB tables, plus WooCommerce order storage. Not wp_postmeta.
| Table | Holds |
|---|---|
| Protections | One row per protected order: the premium, the coverage cap, the plan snapshot, and the coverage window. |
| Claims | One row per claim, against exactly one protection. |
| Claim events | The activity log — every state change, decision and operator note, append-only. |
| Evidence | Uploaded photos, videos and PDFs, linked to a claim. |
| Tracking events | Carrier tracking events ingested from the inbound webhook. |
| Reserve ledger | Every premium collected and every claim paid out, with a running balance. |
| Rules | The auto-decision rules built in the visual rule builder. Pro |
| Fraud signals | The signals the risk profile and rule engine read from. |
| Audit log | Administrative actions, separate from the per-claim activity log. |
| API tokens | Bearer tokens for REST write access, SHA-256 hashed at rest. Pro |
Why custom tables and not post meta
Claims and ledger rows are relational, high-cardinality, and queried by status, date range and order — exactly the access pattern wp_postmeta is worst at. Storing them as meta would mean a self-join per filter and an unindexed scan on every dashboard load.
The full rationale is written up as an architecture decision record in the repository: docs/adr/0001-custom-tables-vs-postmeta.md.
Hooks reference
The filters and actions most relevant to extending or auditing the plugin. Not exhaustive of every internal hook, but it covers every hook that gates free/Pro behaviour, and every hook a merchant developer is likely to reach for.
Licensing & Pro boot
| Hook | Type | Fires |
|---|---|---|
covermyorder/license/is_pro | filter | Anywhere Pro status is checked. Pro's add-on hooks this at priority 1000 to report its own licence state. |
covermyorder/pro/boot | action | Once, after the free plugin confirms a Pro licence is active — Pro registers all of its own service providers here. |
Plans & pricing
| Hook | Type | Fires |
|---|---|---|
covermyorder/plans/allow_multi | filter, default false | The free/Pro gate for the whole Plans screen. Pro flips it to true, which both unlocks multi-plan saving and tells the free single-plan form to hide itself. |
covermyorder/plans/catalog | filter | Augments the hydrated plan list at read time. |
covermyorder/plans/changed | action | After plans are saved — useful for cache invalidation. |
covermyorder/admin/plans/list_view | action | Above the Plans form. Pro renders its entire card list here. |
covermyorder/pricing/strategy_for_model | filter | Resolves which pricing strategy calculates a plan's premium. Pro hooks this to supply percentage pricing — needed for correct checkout pricing on any percentage plan, however it was created. |
covermyorder/pricing/fallback_plan_id | filter | Resolves a fallback plan when a checkout requests a plan id that no longer exists (deleted, deactivated, or a stale cache). |
Branding
| Hook | Type | Fires |
|---|---|---|
covermyorder/branding/text | filter | Overrides cart-toggle and thank-you strings at read time. |
covermyorder/branding/presets | filter | Injects additional colour presets — Pro adds 5 here. |
covermyorder/branding/badge_enabled | filter, default true | Returning false hides the badge — free hardcodes this to always-on. |
covermyorder/branding/placements | filter | Badge position per surface — Pro exposes the picker. |
covermyorder/admin/branding/after | action | End of the Branding settings screen — Pro injects custom hex, logo and placement controls here. |
Settings & evidence
| Hook | Type | Fires |
|---|---|---|
covermyorder/admin/settings/advanced_sections | action | End of the Settings screen — Pro's category-override and global-cap sections render here. |
covermyorder/admin/settings/save_payload | filter | The settings payload just before it is saved — lets Pro persist its own fields on the same submit. |
covermyorder/evidence/max_files_per_claim | filter, default 10 | Maximum evidence files per claim. |
covermyorder/evidence/max_bytes_per_file | filter, default 10 MB | Maximum size per evidence file. |
Worked example: a custom pricing strategy
Every pricing model resolves through one filter, so adding your own is a matter of returning a different strategy object for your own model key.
add_filter(
'covermyorder/pricing/strategy_for_model',
function ( $strategy, string $model ) {
if ( 'weight_banded' !== $model ) {
return $strategy; // not ours — leave it alone
}
return new My_Weight_Banded_Strategy();
},
10,
2
);
REST API
Namespace covermyorder/v1. Read endpoints are available on free; write endpoints require a Pro API token.
GET /wp-json/covermyorder/v1/health
{ "status": "ok", "version": "1.8.0" }
Authentication
| Mode | Used by | Notes |
|---|---|---|
| Cookie + nonce | The admin UI, in a browser context | Standard WordPress REST authentication. |
| Bearer token Pro | External integrations | SHA-256 hashed at rest. Shown once at creation and never again. |
| HMAC signature | Incoming webhooks | Five-minute replay window. Used by the inbound tracking endpoint. |
Endpoints
| Endpoint | Access |
|---|---|
GET /covermyorder/v1/plans | Free · public |
POST /covermyorder/v1/plans/quote | Free · public |
GET /covermyorder/v1/protections | Free · read |
GET /covermyorder/v1/claims | Free · read |
POST /covermyorder/v1/claims | Pro · write (API token) |
POST /covermyorder/v1/tracking | HMAC (webhook ingest) |
Conventions
- Rate limiting. Every response carries
X-RateLimit-*headers. - Errors. RFC 7807 Problem Details, not a bare WordPress error blob.
- Idempotency.
POST,PUTandPATCHhonour anIdempotency-Keyheader with a 24-hour response cache — a retried request returns the original response instead of creating a second claim.
Idempotency-Key on every write. Network retries are not hypothetical, and a duplicate claim on a protected order is a duplicate payout.Webhooks Pro
Outbound claim-event delivery to Slack, Zapier, or any custom URL, HMAC-signed.
POST https://your-endpoint.example.com/hook
User-Agent: CoverMyOrder-Pro/1.8.0
X-CoverMyOrder-Event: claim.approved
X-CoverMyOrder-Signature: sha256=<hmac hex digest>
Content-Type: application/json
{
"event": "claim.approved",
"claim_id": 4821,
"order_id": 10932,
"resolved_amount_cents": 4599
}
Verifying the signature
Compute an HMAC-SHA256 of the raw request body against your configured webhook secret, and compare it to X-CoverMyOrder-Signature with a constant-time comparison.
$signature = $_SERVER['HTTP_X_COVERMYORDER_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac( 'sha256', $raw_body, $secret );
if ( ! hash_equals( $expected, $signature ) ) {
http_response_code( 401 );
exit;
}
Delivery
Deliveries are queued through Action Scheduler rather than sent inline, so a slow or unreachable endpoint never blocks an operator approving a claim in wp-admin. Respond 2xx quickly and do your own work asynchronously — a webhook receiver that takes ten seconds to reply is a webhook receiver that will be treated as failed.
Templates
Every customer-facing view can be overridden from your active theme, WooCommerce-style.
Overridable templates
yourtheme/covermyorder/badge.php
yourtheme/covermyorder/thankyou.php
yourtheme/covermyorder/portal/authenticate.php
yourtheme/covermyorder/portal/dashboard.php
yourtheme/covermyorder/portal/claim-form.php
yourtheme/covermyorder/emails/claim-submitted.php
yourtheme/covermyorder/emails/claim-approved.php
How to override one
- Copy the file out of the plugin
From the plugin's own
views/orthemes/default/covermyorder/folder. - Paste it into your theme at the same relative path
Under a
covermyorder/directory in your active theme — ideally a child theme. - Edit freely
Plugin updates never touch files inside your theme.
License gating
There is no capabilities registry, and no per-feature gate methods to call. The mechanism is simpler than that.
src/Licensing/LicenseGate.php exposes exactly two methods: isPro() and upgradeUrl(). It is used only by the Upgrade tab, to hide itself once Premium is installed. The free plugin does not gate anything internally with it.
Instead: free simply never implements the Pro behaviour. The single-plan form only ever writes a flat fee and a fixed cap because that is all its own code does — not because something is checking a permission and blocking a wider write. Pro then extends or fully replaces a screen through ordinary action and filter hooks, registered when its own licence check (covermyorder/license/is_pro) passes:
covermyorder/plans/allow_multiflips fromfalsetotrue, and the free single-plan form checks this same filter to decide whether to hide itself.covermyorder/admin/settings/advanced_sectionsandcovermyorder/admin/branding/afterare plain extension points free always fires — empty and inert unless Pro is there to hook them.covermyorder/pricing/strategy_for_modellets Pro supply aPercentageStrategyso a percentage-priced plan calculates correctly at checkout, regardless of which screen created it.
covermyorder/pro/boot.