Lifetime license back for a limited time  →
Phox Product Addons Pro — User & Developer Guide

Overview

Product Addons lets you attach extra options to any WooCommerce product — from a simple "add gift wrapping?" toggle to a multi-step product configurator with live price calculation.

Everything is organised into addon groups. A group is a reusable bundle of fields with its own pricing, conditional logic and assignment rules. You build a group once, then assign it to as many products, categories or customer roles as you like. A single product can show several groups at once.

21 field types

Text, numbers, swatches, visual cards, product options, file uploads, date pickers and more — each priced however you like.

Dynamic pricing

Fixed, percentage, per-character, per-word, per-file or custom formula pricing — recalculated server-side.

Conditional logic

Show, hide, require or unrequire fields based on other selections, the cart, the date or the customer.

Live totals

Shoppers see the price update as they configure, with an optional itemised breakdown.

Requirements & installation

RequirementMinimum version
WordPress6.4 or newer
WooCommerce8.0 or newer
PHP8.0 or newer
  1. Install the plugin. In WordPress go to Plugins → Add New → Upload Plugin, choose the phox-product-addons.zip file and click Install Now.
  2. Activate it. A new Product Addons item appears in the main admin menu (look for the layout icon).
  3. Confirm WooCommerce is active. Product Addons extends WooCommerce, so WooCommerce must be installed and active first.
Permissions

Any user who can Manage WooCommerce (shop managers and administrators) can create and edit addon groups. No extra capabilities are needed.

Updating from a previous version

Update in place — replace the files inside the existing phox-product-addons plugin folder, or use the built-in updater. Never upload the new version as a second folder (for example phox-product-addons-latest) alongside the old one: WordPress would load both copies, and the duplicate PHOX_ADDONS_VERSION constant will cause a fatal error. Keep exactly one copy active.

Quick start — your first addon

Let's add an optional gift-wrapping fee to a product in under a minute.

  1. Open Product Addons from the admin menu, then click New Addon Group (or pick a ready-made template — see Starter templates).
  2. Name the group at the top, e.g. "Gift options".
  3. Add a field. On the Fields tab click Add field and choose Toggle Switch. Label it "Add gift wrapping" and set its price to a fixed 3.95.
  4. Assign the group. On the Assignments tab add a target — choose Entire store, or search for specific products or categories.
  5. Set it live. On the Settings tab set Status to Active, then click Save.
  6. Check the product page. The toggle now appears below the product, and ticking it adds £3.95 to the live total and the cart.

The admin interface

The plugin opens on the groups list, where every addon group is shown with its field count, priority and status. From here you can create, duplicate, export, import or delete groups, and toggle the global itemised totals setting.

Opening a group reveals the group editor, organised into four tabs:

TabWhat you configure
FieldsThe options shoppers see — their type, labels, pricing, images and order. Drag to reorder.
AssignmentsWhich products the group appears on, and how it combines with other groups.
LogicRules that show, hide, require or make optional based on conditions, with a live test panel.
SettingsStatus, priority, group type, display mode and the group description.
Tip

The toolbar shows an "Unsaved changes" indicator whenever you have edits in flight. Nothing goes live until you press Save.

Field types

Product Addons ships with twenty-one field types across five categories. Add as many as you like to a group and drag them into any order.

Basic Basic

FieldDescriptionPricing
TextA single-line text input. Supports a placeholder and maximum length.Fixed, %, per-char, per-word, formula
TextareaMulti-line text, ideal for messages or instructions.Fixed, %, per-char, per-word, formula
NumberA numeric input. Can be given a formula variable name so its value feeds calculator formulas.Fixed, %, formula
EmailEmail-validated text input.Fixed, %, formula
TelephonePhone-number input.Fixed, %, formula
URLWeb-address input.Fixed, %, formula

Selection Selection

FieldDescription
CheckboxA single yes/no checkbox with an optional add-on price when ticked.
Checkbox GroupMultiple options where the shopper can tick several at once. Each option carries its own price.
Radio ButtonsMultiple options, one selectable.
Select DropdownA classic dropdown, one selectable.
Multi SelectA dropdown allowing several selections.
Toggle SwitchA modern on/off switch — perfect for "add this" style upsells.
Button GroupOptions rendered as a row of selectable buttons, one selectable.

Visual Visual

FieldDescription
Image DropdownA rich dropdown with a thumbnail, label, description and optional badge per option.
Visual CardsLarge selectable cards with image, title, description and badge. Choose 1–4 columns. Supports single or multiple selection.
Image SwatchesCompact image tiles with a zoom/preview lightbox. Single or multiple selection.
Colour SwatchesColour chips (solid or two-tone). Single or multiple selection.

Products Products

FieldDescription
Product OptionsOffer other WooCommerce products (or specific variations) as selectable options — priced from each product's live price, stock-aware, and added to the order as their own line. See Product options.

Advanced Advanced

FieldDescription
File UploadLets shoppers upload artwork or documents. Single or multiple files, with strict type and size validation. See File uploads.
Date PickerA calendar date input with optional earliest/latest limits.
Time PickerA time input with optional earliest/latest limits.
Date & TimeA combined date-and-time input with optional limits.

Common field settings

Every field shares a few settings: a label, an optional description shown beneath it, and a Required toggle. Text-style fields add a placeholder and maximum length; option fields add an options editor; visual fields add image and badge controls.

Options, images & badges

Selection and visual fields are built from a list of options. For each option you can set:

  • Label — what the shopper sees.
  • Value — the stored identifier used in logic and on the order.
  • Price & price type — a per-option add-on (fixed amount or percentage).
  • Image or colour — for image dropdowns, visual cards and swatches (colour swatches accept a second colour for a two-tone chip).
  • Badge — a small label such as "Popular" or "Bestseller" shown on cards and image dropdowns.
  • Description — extra copy on cards and image dropdowns.

Images are chosen through the standard WordPress media library, so anything already in your media library is available instantly.

Pricing

Pricing is set per field (or per option). Every priced selection is added to the product price, multiplied by quantity, and shown in the live total and the cart. All prices are recalculated authoritatively on the server when the item is added to the cart, so totals can never be tampered with from the browser.

Price typeEffectAvailable on
NoneNo charge.All fields
FixedA flat amount in your store currency.All priced fields
PercentageA percentage of the product price.All priced fields
Per characterAmount × number of characters entered.Text, Textarea
Per wordAmount × number of words entered.Text, Textarea
Per fileAmount × number of files uploaded.File Upload
FormulaA custom expression — see below.All priced fields
Per-unit pricing

Addon prices are calculated per product unit. If a shopper buys a quantity of three, the addon price is applied to each of the three units, exactly like the base product price.

Formulas & calculator groups

Formula pricing turns Product Addons into a made-to-measure calculator. Set a field's price type to Formula and enter an expression such as:

(width * height) * 15

Formulas support +, -, *, / and parentheses. The available variables are:

  • product_price — the current product (or variation) price.
  • quantity — the chosen quantity.
  • Any Number field's formula variable name. For example, set a Number field's variable name to width and another to height, and both become usable in formulas.

Calculator groups

Set a group's type to Calculator and give the group itself a formula. The result is added as a single priced line labelled with the group title — ideal for area- or volume-based pricing where the charge comes from the whole configuration rather than one field.

Tip

Formulas are evaluated with a safe expression parser — never eval — and the result can never go below zero. The same engine runs in the browser (for the live total) and on the server (for the authoritative cart price), so the two always agree.

Conditional logic

The Logic tab lets fields react to what the shopper does. A rule reads as: when these conditions are met, perform these actions.

Actions

ActionEffect
ShowReveals a field. Fields targeted by any Show action start hidden and only appear when a rule passes.
HideHides a field.
RequireMakes a field mandatory.
Make optionalRemoves a field's required status.

Conditions

Conditions can test much more than other fields. Each rule holds one or more condition groups; within a group you choose whether all or any conditions must pass, and you choose whether all or any groups must pass. This lets you build sophisticated AND/OR logic.

Condition typeTests…
Field valueAnother field — equals, doesn't equal, contains, greater than, less than, is empty, is not empty.
Cart totalThe cart subtotal — greater than, less than, equals.
Product in cartWhether a given product is (or isn't) already in the cart.
Category in cartWhether any product from a category is (or isn't) in the cart.
MonthThe current month — great for seasonal options.
Day of weekThe current day, Monday–Sunday.
Logged inWhether the visitor is signed in.
User roleThe visitor's role — e.g. wholesale customers.
Cross-group logic

Rules can target and test fields in other groups assigned to the same product, so a choice in one group can drive a field in another. A built-in test panel lets you trial values and watch the resulting visibility and requirements before going live.

Assignments

The Assignments tab decides where a group appears. Add one or more targets; they are combined with OR, so the group shows whenever any target matches.

TargetMatches
Entire storeEvery product.
Specific productsProducts you search for and select.
Product categoriesAll products in the chosen categories.
Product tagsAll products with the chosen tags.
Product typesSimple, variable, grouped, external, subscription, bundle or composite.
User rolesOnly shoppers with the chosen role.

Combining groups

When several groups match the same product, the group's mode and priority decide how they interact:

ModeBehaviour
MergeThe group is shown alongside other matching groups (the default).
OverrideThe highest-priority matching group replaces all lower-priority ones.
ExcludeThe group is never displayed — useful for temporarily switching one off.

Priority is a number; higher-priority groups load first and win in Override mode.

Display modes & layouts

A group's display mode (on the Settings tab) controls how its fields are laid out on the product page.

ModeLayout
CardsFields stacked as clean cards (the default).
GridFields arranged in a responsive grid.
AccordionEach field is a collapsible panel; the first is open by default.
TabsFields become tabs, shown one at a time.
StepsA wizard with Back/Next navigation and a final review panel summarising every choice.
Tip

Tabs and Steps automatically skip fields that conditional logic has hidden, so shoppers never land on an empty step.

Modal popup New

Instead of showing a group's fields inline, you can tuck them behind a button that opens a popup. Tick Open options in a modal popup on the group's Settings tab — it wraps whichever display mode you've chosen (Cards, Grid, Tabs, Steps and so on), so it works over any layout.

On the product page the shopper then sees:

  • A trigger button in place of the inline fields, with text you set via Modal button text (default "Customise Product").
  • A popup containing all the group's fields plus a live total, opened by the button and dismissed with the close icon, the backdrop or the Esc key.
  • A confirm button — text set via Confirm button text (default "Save options") — which validates the group's required fields before closing. If something's missing the popup stays open and highlights it.
  • Once confirmed, the trigger turns into a summary: a "Customised" tick, the added price, and an Edit link that reopens the popup.
Tip

Modal is ideal when a product has lots of options and you want to keep the product page tidy — the shopper configures everything in one focused dialog, then returns to a clean summary.

File uploads

The File Upload field lets shoppers attach artwork, proofs or documents to their order. You can allow a single file or several, and cap the number of files.

Allowed files & limits

By default the field accepts JPG, JPEG, PNG, SVG, PDF, DOC and DOCX files up to 10 MB each. Both limits can be changed by a developer (see Hooks & filters).

Security

Uploads are validated defensively, so executable files such as .php cannot be uploaded or run:

  • Every file is checked against an allow-list of types — and the file's real contents are inspected, not just its extension, so a renamed script is rejected.
  • Files are stored with randomised names in a dedicated uploads/phox-addons/ folder.
  • SVGs are sanitised to strip scripts and event handlers.
  • The upload folder is hardened with rules that block execution of .php, .phtml, .cgi and similar files and disable directory listing.
Note for nginx hosts

The automatic hardening uses an .htaccess file, which Apache and LiteSpeed honour. On nginx, .htaccess is ignored — add an equivalent server-level rule to block PHP execution under uploads/phox-addons/ for full defence in depth.

Date & time

The Date, Time and Date & Time fields collect scheduling information — delivery dates, appointment slots, event times and so on. Each offers an optional Allowed range with an Earliest and Latest limit shown side by side.

When a range is set, a value outside it is rejected both in the browser (the shopper sees an error and can't add to cart) and again on the server, so an out-of-range date can never reach an order.

Tip

For the Date & Time field, the Earliest/Latest controls capture a full date and time, so you can restrict, say, bookings to between 09:00 and 17:00 on a given day.

Visual cards & swatches

Visual Cards, Image Swatches and Colour Swatches turn flat option lists into a polished, tactile picker. Each supports:

  • Single or multiple selection. Tick Allow multiple selections on the field to let shoppers choose several options at once (they render as checkboxes); leave it off for a one-of-many picker (radio behaviour).
  • Per-option pricing and badges, so a "Premium" card can carry both an upcharge and a label.
  • For Visual Cards, a 1–4 column layout.
  • For Image Swatches, a zoom lightbox so shoppers can preview the full image.
  • Replace the product image — optionally swap the main product photo for the selected option's image (see below).

Replace the product image New

Image Dropdown, Visual Cards and Image Swatches each have a "Replace product image with selected option" checkbox in the field's settings. Turn it on and, when a shopper picks an option that has an image, the product page's main image swaps to that option's image; clearing the choice (or selecting an option without an image) restores the original.

It works with the standard WooCommerce product gallery and with the Phox Elements / Phox Oxygen Product Display element, both detected automatically — so shoppers see the exact variant they're configuring. The original image and its responsive srcset are restored intact when the selection is cleared.

Tip

This is perfect for colour or finish pickers: pair an Image Swatches field with product-lifestyle photos so the hero image updates as the shopper chooses. The toggle is per field, so enable it only where option images should stand in for the product photo.

Product options New

The Product Options field lets you offer other products as selectable options — bundles, cross-sells or an "add a matching item" upsell. Each option points at a real WooCommerce product (or a specific variation), so its price, name and image come straight from that product and stay in sync.

Configuring options

  • Product — search for and pick the product each option represents.
  • Discount — an optional percentage off that product's live price, just for this option.
  • Quantity — how many of the product a single selection adds (defaults to one).
  • Label & badge — override the displayed name and add a small label such as "Popular"; leave the label blank to use the product's own name.
  • Single or multiple selection, rendered as cards with the product thumbnail (choose 1–4 columns).

Pricing & stock

Options are priced from the product's live, sale-aware price (with any per-option discount applied) and multiplied by the option quantity. Because the price is read from the product itself, a later price change or sale on the linked product is reflected automatically. Out-of-stock products are shown as disabled and can't be selected, and any option whose product no longer exists or can't be purchased is skipped everywhere.

On the order

A selected product option is added to the order as its own line item at the (optionally discounted) price, so stock, reporting and fulfilment treat it like any normal purchase. Variable, grouped and external products can't be used as options — pick a simple product or a specific variation.

Starter templates

From the groups list you can create a group from a ready-made template — a fast way to learn the plugin or stand up common patterns. Each is created as a draft so you can review and adjust before going live.

Gift Wrapping

A wrap toggle, wrapping-paper colour swatches and a gift-message textarea, wired with logic so the paper and message appear only when wrapping is enabled.

Engraving

Per-character engraving text with a font choice.

Extended Warranty

Tiered warranty options as a priced selection.

Personalisation

A personalisation bundle for monograms and custom text.

Import & export

Any group can be exported to a JSON file from the groups list, and imported on another site (or the same one). This makes it easy to move configurations between staging and production, or to keep a backup of a complex configurator.

What import does

Imported groups arrive as drafts so nothing goes live unreviewed. Product and category assignments are dropped by default, since those IDs rarely match across sites — re-assign the group after importing (or keep assignments deliberately if you're importing onto the same site).

Product options across sites

Product Options reference products by ID. When you move a group to another site those IDs won't match, so re-pick the linked products after importing — the same way you re-assign the group.

Settings & totals

Per-group settings

SettingPurpose
StatusActive shows the group on matching products; Draft keeps it hidden while you work.
PriorityOrdering/precedence between groups — higher loads first and wins in Override mode.
Group typeStandard, Global, Template or Calculator (Calculator adds a group-level formula line).
Display modeCards, Grid, Accordion, Tabs or Steps.
Modal popupOpen the group's fields in a button-triggered popup instead of inline. Adds Modal button text and Confirm button text. See Modal popup.
DescriptionOptional text shown under the group title on the product page.

Itemised totals

A global toggle on the groups list controls how add-ons appear in the totals box. With itemised totals on, each priced selection gets its own line; with it off, all add-ons are summed into a single "Options" row.

The storefront & cart

On the product page, add-ons appear below the product with a live totals box that updates as the shopper configures. Required fields are validated before the item can be added to the cart. If an image field has Replace product image enabled, the product's main photo also updates as the shopper chooses.

From there, selections flow through the whole order:

  • The shopper's choices and their prices are shown under the item in the cart and at checkout.
  • Add-on charges are added to the line item's price.
  • Selections are saved to the order and appear in admin order details and in order emails.
  • Product Options add the chosen product to the order as its own line item, at the discounted price where set.
  • Uploaded files are linked from the order so you can download exactly what the customer sent.

Data model

Addon groups are stored as a hidden custom post type, phox_addon_group. The entire configuration — fields, options, assignments, logic and settings — is serialised as JSON in the _phox_config post meta.

WhereKey
Group storagePost type phox_addon_group, meta _phox_config
Front-end input namesphox_addons[{field_id}] (array-suffixed for multi-value fields)
Cart item dataphox_addons on the cart item
Order item meta_phox_addons
Server is authoritative

Pricing and logic are implemented twice — once in JavaScript for instant feedback and once in PHP for the cart. The PHP engine always recalculates prices from the raw submitted values, so the browser can never set its own price. Product Options resolve their price live from the referenced product, never from the submitted value.

REST API

The React admin is powered by a REST API under the phox-addons/v1 namespace. All group endpoints require the manage_woocommerce capability.

MethodRoutePurpose
GET/groupsList all groups.
POST/groupsCreate a group.
GET/groups/{id}Fetch one group.
PUT/groups/{id}Update a group.
DELETE/groups/{id}Delete a group.
POST/groups/{id}/duplicateDuplicate a group.
GET/groups/{id}/exportExport a group as JSON.
POST/groups/importImport a group from an export payload.
GET/settings · POST /settingsRead / write global settings.
GET/search/productsSearch products for assignments and Product Options.
POST/uploadPublic shopper upload endpoint (nonce-protected).
Upload endpoint & nonces

The upload route is public (shoppers may be guests) but protected by a nonce plus strict file validation. Any custom code calling it from a logged-in context must send the standard X-WP-Nonce header so the request keeps its user identity — otherwise the upload nonce will fail with a "Session expired" error.

Hooks & filters

Actions

// Render a product's addon groups inside a custom template / page builder.
// Fires the same renderer WooCommerce's product page uses.
do_action( 'phox_addons_product_display', $product );

Filters

// Change which groups apply to a product.
add_filter( 'phox_addons_groups_for_product', function ( $groups, $product ) {
    return $groups;
}, 10, 2 );
// Change the maximum upload size (bytes). Default 10 MB.
add_filter( 'phox_addons_max_upload_size', fn() => 20 * MB_IN_BYTES );
// Change the allowed upload types (extension => mime).
add_filter( 'phox_addons_allowed_upload_types', function ( $types ) {
    $types['ai'] = 'application/postscript';
    return $types;
} );

Front-end JS API

Each rendered addon block exposes a small API on its root element, so custom add-to-cart implementations can validate and read the live total. The block also dispatches a bubbling phox-addons:change event whenever a selection changes.

const root = document.querySelector('[data-phox-addons]');
// Validate required fields before submitting. Returns true if valid.
if ( ! root.phoxAddons.validate() ) return;
root.phoxAddons.refresh();           // recompute visibility & totals
root.phoxAddons.total;               // current per-unit addon total
root.phoxAddons.setProductPrice(p); // override price (variation-aware hosts)
// React to configuration changes.
root.addEventListener('phox-addons:change', (e) => {
    console.log(e.detail.total);
});
Custom add-to-cart

Any custom add-to-cart UI must POST the phox_addons[...] inputs along with the request and should call root.phoxAddons.validate() first. The server re-runs validation and pricing regardless.

Product-image swap

The image-swap runs automatically on the standard WooCommerce gallery and the Product Display element. If your custom gallery uses different markup, ensure the main image matches one of .woocommerce-product-gallery__image img or .ppd-main-img for the swap to find it.

Page-builder integration

Product Addons integrates with custom product templates — including the Phox Elements and Phox Oxygen "Product Display" elements — that don't use WooCommerce's default form.cart.

To render add-ons inside a custom template, fire the action where you want them to appear:

do_action( 'phox_addons_product_display', $product );

Then, in your add-to-cart handler:

  • Call root.phoxAddons.validate() and stop if it returns false.
  • Append the serialised phox_addons[...] fields to the POST body so they reach the cart.
  • For variation-aware layouts, call setProductPrice() when the selected variation changes so percentage and formula pricing follow the live price.

The renderer guards against rendering twice for the same product on a page, so it's safe whether it fires via the standard WooCommerce hook or your custom template.


Troubleshooting

Breakdance or the site shows "Constant PHOX_ADDONS_VERSION already defined"

Two copies of the plugin are active at once — usually the original phox-product-addons folder plus a second upload such as phox-product-addons-latest. WordPress loads both, and the second defines the same constant, which triggers a fatal error. Deactivate and remove one copy so only a single phox-product-addons folder remains, then update in place rather than adding a parallel folder.

The group doesn't appear on the product

Check that its Status is Active (not Draft), that it has at least one Assignment target matching the product, and that its mode isn't set to Exclude. If another matching group uses Override at a higher priority, it may be replacing this one.

A product option isn't showing

Product Options skip anything that can't be sold: a product that's out of stock appears but is disabled, and an option whose product has been trashed, set to draft, or changed to a variable/grouped/external type is dropped entirely. Point the option at a purchasable simple product or a specific variation.

The product image doesn't swap

Confirm the field has Replace product image with selected option ticked and that the chosen option actually has an image. The swap targets the standard WooCommerce gallery and the Phox Product Display element; a heavily customised or third-party gallery may use different markup (see Front-end JS API).

A file upload says "Session expired. Please reload the page"

This means the upload's security nonce didn't validate. It most often happens when a product page is served from a cache for a long time, or when a custom add-to-cart calls the upload endpoint without forwarding the logged-in session. Reload the page to refresh the nonce; for custom integrations, send the X-WP-Nonce header (see REST API).

The live total looks wrong

The cart price is always recalculated on the server, so the cart is the source of truth. If the browser total disagrees, it's usually a stale cached copy of the plugin's script — clear any page/CDN cache. Hidden fields (via logic) are never charged.

New features or styles aren't showing

Clear your site and browser caches. The plugin versions its assets automatically, but aggressive CDNs sometimes hold an old copy.

FAQ

Can one product show several addon groups?

Yes. Every group whose assignment matches the product is shown (in Merge mode), and logic can even reference fields across those groups.

Are add-on prices charged per item?

Yes — add-on prices are per unit and are multiplied by the quantity, just like the base product price.

Can I offer other products as add-ons?

Yes — use the Product Options field. Each option links to a real product or variation, is priced from its live price (with an optional discount), respects stock, and is added to the order as its own line item. See Product options.

Can an option change the product image?

Yes. On image fields, enable Replace product image with selected option and the main product photo swaps to the chosen option's image, restoring when the choice is cleared. See Visual cards & swatches.

Can shoppers select more than one visual card or swatch?

Yes. Enable Allow multiple selections on the field and it behaves like a checkbox group while keeping the visual styling.

Is it safe to let customers upload files?

Yes. Uploads are restricted to an allow-list of document and image types, validated by real content rather than extension, stored with randomised names, and the folder is hardened against script execution. SVGs are sanitised. See File uploads.

Can I move a configuration between sites?

Yes — export the group to JSON and import it elsewhere. It arrives as a draft with assignments cleared, ready to review and re-assign. Re-pick any Product Options, since they reference products by ID.


Phox Product Addons Pro · v1.1.0 · by Phox Elements · Built for WooCommerce. For the latest information visit phoxelements.com.

Phox Elements contains 130+ unique elements for Breakdance...with more to come

I'm a cat. This is a breakdance popup