Skip to main content

Product Options

Overview​

Product Options groups configurable inputs into option sets that are attached to products, categories, tags, or everything at once. Where Product Add-Ons defines each input individually, an option set is one reusable bundle — "Engraving", "Gift wrapping", "Framing" — assigned wherever it applies and edited in one place.

A set's fields are stored as JSON on the set itself, along with its conditional logic, so adding a field to a set changes every product the set is attached to. Pricing supports a fixed amount, a percentage, and a formula evaluated against the product's price and the entered value.

It is for stores where the same configuration repeats across a catalogue.

Availability​

ItemValue
Module keyproduct_options
TierPremium
Entitlement keyproduct_options
Admin tabproduct-options
Enabled optionaiowc_module_enabled_product_options (off until turned on)
REST namespaceaiowc/v1

Enabling the module creates the three tables below and schedules the file cleanup job.

registerHooks() performs no licence check of its own; the module registry applies the entitlement gate centrally before calling it.

Settings​

This module has no settings row. It declares no settings prefix and no defaults, so there is nothing at aiowc_po_settings or any equivalent. Everything is configured per option set, and the two numeric upload limits are filters rather than stored settings — see Uploads below.

Option sets​

FieldMeaning
name, slugWhat the set is called, and its stable identifier.
descriptionAn internal note.
is_globalWhether the set applies to every product regardless of assignments.
priorityThe order sets are applied in when several reach one product.
statusdraft, active or archived. A new set is draft by default.
fieldsThe set's fields, stored as JSON.
conditional_logicRules that show or hide fields based on other answers, stored as JSON.

A set is draft until it is made active, so creating a set and assigning it is not enough on its own to make it appear on the storefront.

Assignments​

An assignment attaches a set to a target:

target_typeAttaches the set to
productOne product, by id.
categoryEvery product in a category.
tagEvery product carrying a tag.
allEvery product.

Assignments carry their own priority, so a product-level assignment can be ordered ahead of a category-level one.

Field validation​

Each field carries validation rules, applied when the customer submits: required, a minimum and maximum value, a minimum and maximum length, and a regular-expression pattern. A pattern without delimiters is given them before use, so a plain expression works as written.

Pricing​

TypeEffect
fixedAdds a fixed amount.
percentAdds a percentage of the product's price.
formulaEvaluates an arithmetic expression.

A formula may use the placeholders {base_price}, {value} and {qty}, and the operators +, -, *, / with parentheses. It is parsed into tokens and evaluated by the module itself — not by PHP's evaluator — and the tokeniser accepts only digits, a decimal point, those four operators, parentheses and whitespace, so a formula cannot be used to run code. Division by zero yields 0.0 rather than an error, and a non-numeric entered value is treated as 0.

Uploads​

A file field posts to /product-options/upload. Uploads accept image/jpeg, image/png, image/gif, image/webp and application/pdf, up to 5 MB. Both limits are filters rather than settings — aiowc_product_options_allowed_mime_types and aiowc_product_options_max_upload_bytes — so changing either needs a snippet, not an admin control.

An uploaded file is recorded against the visitor's session with an expiry, and claimed by an order when checkout completes. Files that are never claimed are removed by the cleanup job.

Admin screen​

The Product Options tab lists the option sets and creates, edits, duplicates and deletes them, edits each set's fields and conditional logic, and manages the assignments that decide which products a set reaches.

REST API endpoints​

All routes are on aiowc/v1 and answer with the { success, data, message } envelope.

MethodPathPurposePermissionRequired args
GET/product-options/option-setsEvery option set.manage_woocommerce–
POST/product-options/option-setsCreate an option set.manage_woocommercename
GET/product-options/option-sets/{id}One option set.manage_woocommerceid
PATCH / PUT /POST/product-options/option-sets/{id}Update a set. All three verbs are registered.manage_woocommerceid
DELETE/product-options/option-sets/{id}Delete a set.manage_woocommerceid
POST/product-options/option-sets/{id}/duplicateCopy a set, with its fields.manage_woocommerceid
GET/product-options/option-sets/{id}/assignmentsThe set's assignments.manage_woocommerceid
POST/product-options/option-sets/{id}/assignmentsAttach the set to a target.manage_woocommerceid, target_type
DELETE/product-options/assignments/{id}Remove an assignment.manage_woocommerceid
GET/product-options/products/{id}/option-setsThe sets that apply to one product.Public, rate-limitedid
POST/product-options/uploadUpload a file for a file field.Upload check–
DELETE/product-options/upload/{fileId}Discard an upload before checkout.Upload checkfileId

WooCommerce integration​

HookWhat the module does
woocommerce_before_add_to_cart_buttonDraws the option fields on the product page.
woocommerce_add_to_cart_validationRefuses the add when a required field is empty or a rule fails.
woocommerce_add_cart_item_dataCaptures the answers into the cart item.
woocommerce_cart_item_keyMakes the answers part of the cart item's identity, so two differently configured copies of one product stay separate lines.
woocommerce_before_calculate_totalsApplies the pricing.
woocommerce_get_item_dataShows the answers in the cart and at checkout.
woocommerce_checkout_create_order_line_itemWrites the answers onto the order line.
woocommerce_checkout_order_processedClaims the uploaded files for the order.
woocommerce_order_item_name / _meta_endShows the configuration on the order.
woocommerce_before_order_itemmetaShows it on the admin order screen.
wp_enqueue_scriptsLoads the option-field assets.

Database schema​

TableHolds
{prefix}aiowc_option_setsThe set: name, slug, description, global flag, priority, status, and its fields and conditional logic as JSON.
{prefix}aiowc_option_set_assignmentsWhich sets reach which targets: the set, the target type and id, a priority.
{prefix}aiowc_uploaded_filesFiles awaiting an order: the file id, the session, the set and field, the original name, size and MIME type, the claiming order, and an expiry.

The fields and conditional_logic columns are MySQL JSON, so this module needs a database that supports that type.

Background jobs​

HookWork
aiowc_product_options_file_cleanupDeletes uploaded files that passed their expiry without being claimed by an order.

Action hooks for integrators​

HookPurpose
aiowc_product_options_max_upload_bytesFilter — the upload size limit. Default 5 MB.
aiowc_product_options_allowed_mime_typesFilter — the accepted MIME types.
aiowc_product_options_set_createdAn option set is created.
aiowc_product_options_set_updatedAn option set is updated.
aiowc_product_options_set_deletedAn option set is deleted.
aiowc_product_options_set_duplicatedAn option set is copied.
aiowc_product_options_assignment_createdA set is attached to a target.
aiowc_product_options_assignment_deletedAn assignment is removed.
aiowc_product_options_delete_fileAn unclaimed upload is discarded.
aiowc_track_event, aiowc_capture_errorModule lifecycle events and caught errors.

This is the richest integrator surface of the product-configuration modules; a store can react to every set and assignment change without polling.

Entitlement limits​

product_options is an on/off grant with no cap on the number of sets, fields or assignments.

Health check​

The module reports a warning when its tables are missing or WooCommerce is inactive, and otherwise reports that it is functioning normally. A disabled module reports that it is disabled.

Known gaps​

  • A new option set is created as a draft, and a draft set is not applied on the storefront. Creating a set and assigning it is not sufficient; it must also be made active, which is easy to miss.
  • The upload size and MIME allowlist are filters with no admin control, so changing them requires code.
  • With no settings row there is no storefront kill switch: the module is either on, with all its hooks, or disabled entirely.
  • Two modules can attach inputs to the same product — this one and Product Add-Ons — and they keep separate tables, separate admin screens and separate order line data. Nothing reconciles them or warns that both are active.