OptionKit Add-ons — Documentation
Guide to installing and using OptionKit Add-ons (version 0.5.4). The plugin is standalone, so this page covers all of it. Product page: OptionKit Add-ons.
1. Installation
- Install and activate WooCommerce 8.0 or newer.
- In WordPress, go to Plugins → Add New → Upload Plugin and upload the OptionKit Add-ons zip file you downloaded from WPBay. Updates are delivered through WPBay.
- Activate OptionKit Add-ons on the Plugins screen. Everything works straight away; there is no key or account to enter.
- Open WooCommerce → OptionKit Add-ons.
Coming from the free OptionKit plugin? You do not need to deactivate it first: while OptionKit Add-ons is active, the free plugin pauses itself and shows a notice. Both use the same option groups, so your groups, fields and assignments are there immediately. You can then deactivate the free plugin.
If WooCommerce is missing, inactive or older than 8.0, the plugin shows a notice and does nothing else until WooCommerce is ready.
2. Requirements and compatibility
| Item | Requirement |
|---|---|
| WordPress | 6.3 or later (tested up to 7.1) |
| PHP | 7.4 or later (tested on 7.4 and 8.4) |
| WooCommerce | 8.0 or later, required (tested up to 11.1) |
| Order storage | High-Performance Order Storage (HPOS) and legacy posts storage; compatibility with HPOS is declared |
| Cart and Checkout blocks | Supported through the Store API, including the cart's "Edit options" link |
| Who can manage | Users with the manage_woocommerce capability (store managers and administrators) |
| Web server | Apache and IIS protect customer uploads automatically; nginx needs one rule (see Upload folder protection) |
3. Where to find things
All screens are under the WooCommerce menu:
| Menu item | What it is for |
|---|---|
| OptionKit Add-ons | Option groups: list, add, edit, export and import; a Status box (WooCommerce version, order storage, database tables) |
| Lookup tables | CSV price tables used by the "Lookup table" price |
| Starter templates | Ready-made groups installed as drafts |
| Option analytics | Reports on option use and revenue |
| Import add-ons | Importers for other add-on plugins' data, with dry run |
| OptionKit Add-ons settings | Delete data on uninstall, Option statistics, Keep statistics for, Upload limits, Customer uploads (storage usage), Upload folder protection |
On each product's edit screen, the Product data → OptionKit tab holds Local option groups for that product.
4. Creating an option group
- Open WooCommerce → OptionKit Add-ons and click Add group, or install a starter template.
- Enter a Name (and optionally a Slug).
- Choose a Status: Draft groups are never shown to customers; Active groups are.
- Set a Priority: when several groups apply to one product, lower numbers are shown first.
- Pick a Layout (see Group layouts) and an optional Shipping hint.
- Choose the products under Assignment and click Create group.
- Click Add field for each field.
There is no limit on the number of active groups or fields per group.
5. Field types and settings
OptionKit Add-ons has 13 field types:
| Type | Use |
|---|---|
| Text | One line of text (up to 500 characters unless you set a lower max length). |
| Text area | Several lines; line breaks are kept (up to 5,000 characters unless you set a lower max length). |
| Number | A number with optional min, max and step. |
| Dropdown, Radio buttons, Checkboxes | Choices with their own prices; can be shown as swatches. |
| Range slider | A slider with min, max, step and a unit (see Date and range fields). |
| Date | A date picker with earliest and latest day and an optional "No weekends". |
| File upload | A private customer upload (see File uploads). |
| Calculated fee | A fee worked out by a formula or lookup table; the customer enters nothing. |
| Signature | A signature pad; the drawing is stored as a PNG with the upload system. |
| Shortcode / HTML | Display-only content on the product page. |
| Repeater (multiple entries) | 1 to 20 entries of the same small set of sub-fields (see Repeater fields). |
Settings every field has
- Label, Description, Placeholder, Default, Required (when visible), Sort.
- Field price: the price type and amount for single-value fields (see Pricing types).
- Limits: max length for text; min, max and step for number and range fields. The step is checked again on the server, counted from the minimum (or 0); a value off the step is refused at add to cart.
- Key: a short name (letters, numbers, underscores), for example
width, so formulas and lookup tables in other fields can use this field's value. The namesbase,qty,value,lenandcountare reserved and get anf_prefix. - Choices (dropdown, radio, checkboxes): label, value, price, and for swatches a color or image; plus a weight per choice.
- Conditions: see Showing and hiding fields.
6. Pricing types
Prices are previewed live on the product page and always recalculated on the server when the product is added to the cart or the cart is updated.
| Price type | How it is charged |
|---|---|
| None | No charge. |
| Flat | The amount is added to each item, so it is multiplied by the quantity. |
| % of base | A percentage of the product price (the variation's price for variable products), added to each item. |
| Per qty | The amount per item, multiplied by the quantity (same calculation as Flat). |
| One-time | Added once per cart line, whatever the quantity. |
| Formula | The result of a formula, either per item (× quantity) or once per cart line (see Formulas). |
| Lookup table | A value looked up in a CSV table, per item or once per cart line (see Lookup tables). |
| Per entry (repeater) | For repeater fields: the amount for each entry after the free entries, per item (× quantity). |
- Choice fields use the choice's price; each ticked checkbox adds its own price. Single-value fields use the field price and are charged only when the customer enters a value (Calculated fee fields are always priced).
- Role prices: on the field price you can enter a different amount per WordPress user role. When the shopper has a matching role, that amount replaces the field's amount for Flat, % of base, Per qty and One-time prices.
- First choices free (checkboxes): the N cheapest selected choices cost nothing.
- One-time amounts are shown by WooCommerce spread over the line's unit price. A line's unit price never goes below zero.
7. Assigning groups to products
- All products; Product IDs (include, comma-separated); Product IDs (exclude); Categories and Tags (ticked terms). Categories are listed as a tree, and a group assigned to a category also applies to products in its subcategories, at any depth (for example, a group on Furniture also reaches products that are only in Furniture → Tables → Desks). Category excludes from a JSON import cover subcategories the same way.
- Local option groups: on a product's Product data → OptionKit tab, tick active groups that always apply to that product, in addition to global assignments.
- Only Active groups are shown; several groups on one product are shown in priority order.
8. Showing and hiding fields
In the field editor under Conditions:
- Choose Show this field or Hide this field.
- Choose when all conditions match (AND) or when any condition matches (OR).
- In each condition row choose a field from the same group, a comparison (equals, does not equal, contains, is empty, is not empty, is checked, is not checked) and a value. For choice fields, compare with the choice's value; the value box suggests the chosen field's choice values.
- Click Add condition for another row, or Remove to delete one. Rows without a field are ignored, and a field with no conditions is always shown.
Example: show Engraving when Size equals l and Material equals metal; show Card message when Size equals s or Gift is checked wrap.
Conditions are saved in the same format as a group's JSON export, so they survive export and import and reopen in the editor exactly as saved. A condition must point at another field of the same group; conditions on a deleted field are removed when you save. Nested condition groups brought in through JSON (see JSON export and import) are kept when you save the field; the editor notes them, and each counts as one more condition in the AND/OR match.
The rows are keyboard accessible: every control has a numbered label for screen readers (for example "Condition 2: field"), Add condition moves focus to the new row, Remove moves focus to the next row, and additions and removals are announced.
Hidden fields are not charged and not required. The server applies the same rules and drops values sent for hidden fields.
9. Formulas and calculated fees
Choose the Formula price on a field, or add a Calculated fee field (always priced by its formula, never asks the customer for input). Enter the formula under Price formula and choose per item (× quantity) or once per cart line.
| Part | Available |
|---|---|
| Variables | base (product price), qty (quantity), value (this field or chosen choice as a number), len (characters without spaces), count (choices picked), and any other field by its Key. A checkbox field's key gives the number of ticked choices; an upload field gives 1 when a file is attached. |
| Functions | min(a, b, …), max(a, b, …), round(x) or round(x, digits) (0–6), ceil(x), floor(x), abs(x), clamp(x, low, high), if(condition, then, else) |
| Operators | + - * / % ^ < <= > >= == != && || ! |
max(5, width * height * 0.02) area fee with a 5.00 minimum
if(len > 10, len * 0.5, 5) engraving: 5.00 up to 10 characters, otherwise 0.50 per character
clamp(value * 0.1, 1, 20) 10% of a number field, between 1 and 20
- Formulas are parsed by a small built-in calculator into a syntax tree with a fixed list of variables and functions. They are never run as PHP or JavaScript code. The product page uses a JavaScript copy of the same calculator, so the preview matches the server.
- Division by zero gives 0. Unknown variables count as 0. A formula with an error is priced at 0 and the field editor shows the error.
- Up to 500 characters per formula.
10. Swatches
For dropdown, radio and checkbox fields, set Choice style to Text buttons, Color swatches or Image swatches (or keep Default). On each choice row, enter a color (#hex) or pick an image from the media library with the Image button. Swatches are real radio buttons and checkboxes underneath, so they work with the keyboard and screen readers; the visible label names each swatch.
11. Date and range fields
- Range slider: uses Min, Max and Step under Limits (defaults 0, 100 and 1) and an optional Range unit such as
cm. Values outside the range are refused on the server. - Date: under Date limits, set Earliest and Latest as days from today (in the site's time zone) and tick No weekends if needed. Dates outside the limits, invalid dates and weekend dates (when excluded) are refused on the server.
12. File uploads
- Under File upload in the field editor, tick the allowed types:
jpg,jpeg,png,gif,webp,pdf,txt(default: jpg, jpeg, png, pdf). SVG, HTML, scripts and archives are never accepted. - Set Max size (MB) (default 5). It cannot exceed your server's upload limit, which the editor shows.
- The customer's browser uploads the file before add-to-cart. Its content is checked for its format (table below), it is renamed to a random name without extension and stored in
wp-content/uploads/optionkit-secure/, outside the media library, with.htaccessandweb.configdeny rules. - Upload limits (see below) stop one visitor or bot from filling your disk.
- Store managers download files from the order screen through a link that checks their permission; customers and visitors cannot use it.
- Files that are never ordered are deleted by an hourly clean-up after 24 hours (setting Delete uploads not ordered after). A file still in a live cart is kept, but never longer than 7 days. Ordered files stay with the order, and are deleted on an erasure request when WooCommerce is set to remove personal data from orders.
What is checked for each file type
The file name and the browser's stated type are never trusted on their own. A file is accepted only when its content passes the check for its type:
| Type | Content check |
|---|---|
| JPEG, PNG, GIF, WebP | The file signature (first bytes) must match the extension; PHP's fileinfo must detect the same image type; the image must decode as that type (getimagesize) and be at most 12,000 pixels wide or high; files containing <?php or script tags (image/PHP polyglots) are refused. |
Must start with %PDF- and contain %%EOF in the last 2 KB; fileinfo must detect application/pdf. PDFs that declare JavaScript (/JS, /JavaScript), launch actions (/Launch), embedded files, /RichMedia or XFA forms are refused, including hex-escaped names and compressed streams. This is a structural safety check, not a full PDF parser or virus scan. | |
| Plain text (.txt) | UTF-8 or ASCII, no NUL bytes, no HTML, PHP or script tags, at most 2 MB; fileinfo must detect a text type that is not HTML, PHP, script or XML. |
If the server's PHP has no fileinfo extension, the signature and structure checks still run. No other formats can be enabled: the optionkit_pro_upload_types filter can only remove types.
Upload limits
Set under WooCommerce → OptionKit Add-ons settings → Upload limits (0 = no limit). Every upload must fit all of them, so starting a new session or clearing cookies does not reset the IP address or store limits:
| Limit | Default |
|---|---|
| Per guest IP address (IPv6 grouped by /64), per hour | 30 files, 100 MB |
| Per guest session, per hour | 30 files |
| Per customer account (logged in), per hour | 60 files, 250 MB |
| Whole store, per hour | 500 MB |
| Whole store, uploads waiting to be ordered | 2,000 files, 1 GB |
Counters are atomic database updates, so parallel requests cannot go over a limit. Over a limit the visitor sees a short message and the response is HTTP 429 with a Retry-After header. The settings screen shows pending upload storage and this hour's total. Only a one-way keyed hash of the IP address is stored, never the address, and the hourly counters are deleted about two hours after the hour ends. The IP address comes from REMOTE_ADDR; behind a trusted reverse proxy, return the real client IP with the optionkit_pro_upload_client_ip filter. Developers can also adjust the limits with the optionkit_pro_upload_limits filter.
13. Upload folder protection (nginx)
WooCommerce → OptionKit Add-ons settings → Upload folder protection shows the folder, the web server and the last result. Check now writes a random test file into the folder, requests it once from your own site, then deletes it. No other site is contacted. The result is one of:
- Protected: direct requests to the folder are refused (or the folder is outside the web root).
- Exposed: the test file could be downloaded by direct URL. An admin notice reminds you on the Plugins screen and the plugin's screens until the check passes.
- Could not finish: your site could not request its own address (loopback blocked). Check the folder by hand.
Apache and IIS read the generated .htaccess / web.config. nginx ignores them, so add this inside your site's server block, reload nginx (nginx -t then systemctl reload nginx, or your host's equivalent), and click Check now:
location ^~ /wp-content/uploads/optionkit-secure/ {
deny all;
return 404;
}
The settings screen prints this rule with your site's actual path; use that path if your uploads folder is elsewhere. Alternatively, move the folder outside the web root by adding this line to wp-config.php:
define( 'OPTIONKIT_PRO_UPLOAD_DIR', '/path/outside/webroot/optionkit-secure' );
14. Signature, shortcode/HTML, first choices free, weight and role prices
- Signature: a drawing pad with a Clear button. The signature is saved as a PNG (up to 1 MB) through the same private upload system and is shown as "Signed" in the cart and order. It needs a pointer (mouse, touch or pen).
- Shortcode / HTML: content you write (HTML filtered like post content, shortcodes run) shown on the product page. It is display-only and not submitted with the cart.
- First choices free: on a checkbox field, enter N (0–50); the N cheapest selected choices are free. 0 turns it off.
- Weight delta (kg): on a field (when it has a value) or on a choice (when selected). The amount is added to the cart's total weight, multiplied by the quantity, in your store's weight unit. Shipping methods that use the cart's total weight see it.
- Shipping hint (group setting): a short note shown near the options total, for example "Heavier options may change shipping".
- Role prices: see Pricing types.
15. Repeater fields
A repeater lets the customer add several entries of the same sub-fields, for example a name, number and size per team shirt.
- Add a field of type Repeater (multiple entries).
- Under Repeater entries, enter one sub-field per line as
key | Label | type | options. Types:text(options = max length),number(options = min-max),select(options = comma-separated choices). End a label with*to make it required. Up to 6 sub-fields. - Set Min entries, Max entries (up to 20), Free entries and the "Add" button text.
- For a price per entry, choose the Per entry (repeater) price: the amount is charged for each entry after the free ones, per item (× quantity). A Flat price charges its amount once per item, however many entries there are.
name | Name* | text | 20
number | Shirt number | number | 0-99
size | Size* | select | S, M, L, XL
Entries are checked on the server, saved with the cart line and order, and can be changed from the cart. Adding and removing entries is announced to screen readers.
16. Lookup tables (CSV)
Lookup tables give a price from one or two values, for example width × height or size × material.
- Go to WooCommerce → Lookup tables → Add lookup table. Enter a name, choose 1 or 2 axes, optional axis labels, and paste the CSV.
- In a field (often a Calculated fee field), choose the Lookup table price, pick the table, enter the axis fields (other fields' Keys, or
value,base,qty) and choose per item or once per cart line.
CSV format, one axis: each line is label,price. Two axes: the header row is ,col1,col2,…, then each row is rowlabel,price,price,….
S,5
M,7.5
L,10
,oak,walnut
60,120,150
80,140,175
100,160,199
- Labels are matched exactly as text (so
80matches the value 80, not 79 or 81). A value with no matching cell is priced at 0. Use dropdowns or a number field with a step that matches your labels. - Cells must be numbers. Limits: up to 200 labels per axis, 5,000 cells and 500 KB of CSV per table.
- Lookups are plain table reads (no code is run); the live total uses the same tables.
17. Starter templates
WooCommerce → Starter templates: click Install as draft group on a card. Each install creates a new draft group (existing groups are never overwritten); assign it and set it to Active.
| Template | Contents |
|---|---|
| Engraving | Optional engraving text, 40 characters, flat fee 5.00 |
| Gift wrap | Required radio "No thanks" / "Yes, wrap it" (3.50) and an optional gift message (200 characters) |
| Pizza toppings | Five checkbox toppings (1.00–2.50) with the first two free |
| Measurement | Width and height in cm (1–500, step 0.1) and an "Area fee" calculated fee: max(5, width * height * 0.02) |
Amounts are in your store currency; change them after installing.
18. Importing from other add-on plugins
WooCommerce → Import add-ons reads data that the other plugin already stored in your WordPress database (product meta and its own post types). It never downloads or includes the other plugin's code, and it never changes the other plugin's data.
- Choose the source: WooCommerce Product Add-Ons, PPOM (Themeisle) or ThemeComplete Extra Product Options.
- Click Dry-run (no writes). The report lists what is Mapped, what Would create, what Needs manual follow-up, what was Skipped and any Errors.
- When the report looks right, click Import. Groups are created as Draft; review them, then set them to Active.
| Source | What is imported |
|---|---|
| WooCommerce Product Add-Ons | Per-product add-ons (up to 200 products per run): text, textarea, number, checkbox, multiple choice, select and file upload fields with their choices and choice prices. Each product's group is assigned to that product. |
| PPOM | PPOM field groups: text, textarea, number, select, radio, checkbox, date, file, image and color fields, with choices and choice prices. Groups are created without assignments. |
| ThemeComplete EPO | Global forms (up to 100): field types and labels for text, textarea, date, range, color, select, radio, checkbox and upload elements. Choices and prices are not imported. Product-level EPO data and nested builder data are listed for manual follow-up. |
Conditional rules, field-level prices and field types without an equivalent are not imported; they are listed in the report so you can recreate them.
19. Group layouts
Choose the Layout on the group's edit screen:
- Stacked: all fields, one after another (default).
- Accordion and Tabs: fields grouped visually; tabs follow the arrow-key pattern and accordion headers are buttons.
- Steps: one field at a time with Next and Back and a "Step x of y" indicator; focus moves to each step.
- Popup: fields behind a "Customize options" button in a dialog; focus returns to the button when it closes.
If a required field is inside a closed tab, step, accordion or popup, it is revealed and focused before the error message appears.
20. Editing options from the cart
Each cart line with options gets an Edit options link in the classic cart and the Cart block. It opens the product's fields in a dialog; Update cart item saves the changes after the same server checks as add-to-cart, with recalculated prices.
21. Option analytics and retention
WooCommerce → Option analytics shows, for the last 7, 30, 90 or 365 days or custom dates (site time zone):
- Paid orders, orders with options, revenue from paid options, attachment rate, average order with and without options, and order value lift.
- Most used options and most selected choices.
- Per product: cart lines, lines with options, attachment rate, option revenue, average per unit with and without options, and lift.
How it is counted. At checkout each order line gets a small hidden summary of its option amounts (product, quantity, amount per field and per chosen choice; typed-in text is never included). When the order becomes paid, the summary is added to daily totals and the order is stamped with the day it was counted. If the order is later cancelled, refunded or failed, its amounts are subtracted again. Attachment rate is the share of cart lines with at least one option among lines for products that offer options. Option revenue is the option amounts charged at checkout, before coupons.
Settings (WooCommerce → OptionKit Add-ons settings):
- Option statistics: on by default; untick to stop collecting.
- Keep statistics for: 30, 90, 180, 365 (default) or 730 days. A daily clean-up deletes older daily totals.
Rebuild from orders recounts paid orders inside the retention period (up to 5,000 per run, oldest first). Orders placed before version 0.5.0 count option use but not option revenue. Delete all statistics empties the table.
22. JSON export and import
On the option groups screen, Export JSON downloads a group with its fields, choices, prices, conditions, layout and assignments. Import group (JSON) creates a new Draft group from such a file. Assignments refer to product, category and tag IDs, which can differ between sites, so check them after importing elsewhere. A rule's top-level conditions can list several fields with "match": "all" (AND) or "match": "any" (OR).
23. Accessibility
- Every field has a label; descriptions and prices are linked to inputs. Radio and checkbox choices, including swatches, are grouped and named.
- Tabs, accordion, steps and popup are keyboard-operable with focus handling. Visible focus outlines and reduced-motion support.
- Totals are announced politely after typing pauses. A missing required option shows an inline message tied to the field and moves focus to it.
- Repeater entries are grouped and adding or removing one is announced.
- The signature pad needs a pointer and is not keyboard-operable; offer an alternative in your store policy if signatures are required.
Please report any barrier to admin@007aj.com.
24. Performance
- No OptionKit scripts or styles load on pages without option fields (home, shop, products without options).
- Upload/signature, layout and repeater scripts are separate files loaded only on products that use them. A typical option product loads about 11 KB of script and 3 KB of styles, gzipped.
- Resolved option groups are cached between requests in one non-autoloaded option (cleared on every change and after at most one hour), so a product page needs very few database queries.
25. Privacy and personal data
What is stored
- Option values a customer chooses or types in are kept with the cart item and saved with the order items, on your site only, as long as the order.
- Uploaded files (file and signature fields) are stored privately with their original name, type and size. Files never ordered are deleted after 24 hours; ordered files are kept with the order.
- Upload limits keep hourly counters per visitor: for guests a one-way keyed hash of the IP address (never the address itself), deleted about two hours after the hour ends.
- Analytics: a hidden option summary on each new order line and the day a paid order was counted, plus daily totals in the
okt_stats_dailytable. The totals contain no names, email or IP addresses, order or customer numbers and no typed-in text, so they are not personal data; they are deleted after the retention period.
Export and erasure
Option values are included in Tools → Export Personal Data. On Tools → Erase Personal Data, when WooCommerce is set to remove personal data from orders on erasure requests (WooCommerce → Settings → Accounts & Privacy):
| Removed | Kept |
|---|---|
| Option values on that customer's orders (anonymised); files uploaded with those orders (deleted); the hidden analytics summary on each line and the order's counted-on day | Option prices as part of the order totals; anonymous daily analytics totals (they contain no personal data) |
When WooCommerce is set to keep order data, option values and files are kept with the order and the eraser reports that they were retained.
Suggested privacy policy text (including paragraphs on uploads and statistics) is added under Settings → Privacy. The plugin sends nothing to 007AJ or anyone else; its only HTTP request is the upload folder loopback check described above. Privacy policy of the plugin author: https://007aj.com/privacy.
26. Deactivating, uninstalling and deleting data
Deactivating stops the plugin and its daily clean-up events but keeps your data. Deleting the plugin keeps settings, option groups and statistics unless you first tick Delete data on uninstall in the settings; then the settings, statistics table, cache and option group tables are removed. If the free OptionKit plugin is still installed, the shared option group tables are kept for it (the statistics table is always removed). Options already saved on orders are never removed.
27. Known limits
- Conditions: conditions compare fields of the same group. The field editor edits one level of AND/OR conditions; nested condition groups come from JSON import and are kept, not edited, in the field editor.
- Repeater: sub-fields are text, number or select only; a repeater cannot be a condition source or a formula variable; there is no repeater starter template.
- Cart editing: the dialog does not start signature pads or layouts (tabs, steps and similar); those fields are shown one after another.
- Signature pad: needs a pointer; not keyboard-operable.
- Analytics: partial refunds are not subtracted (only cancelled, refunded and failed orders are). Rebuild handles up to 5,000 orders per run, and orders placed before 0.5.0 have no option revenue figures.
- nginx: the upload folder rule must be added by hand; the plugin cannot write server configuration.
- Lookup tables: exact label matches only; no interpolation between rows.
- Imports: best-effort mappings; conditional rules and complex builder layouts are not imported.
- Assignment: excludes in the group screen are by product ID (category excludes are possible through JSON import).
28. Questions
Do I need the free OptionKit plugin too?
No. OptionKit Add-ons is standalone. If the free plugin is active it pauses itself.
Do I need a key or account?
No. Nothing is locked and nothing is checked remotely. Updates are delivered through WPBay.
Why does a lookup table price show 0?
The value did not match a label exactly, or an axis Key is wrong. Check that the axis fields' Keys are entered in the field's Lookup table settings and that the values match the CSV labels.
Why does my formula give 0?
The field editor shows a "Formula error" message if the formula cannot be read. Unknown keys count as 0, so check spelling against the other fields' Keys.
My server is nginx. Are customer uploads safe?
Not until you add the rule in Upload folder protection (or move the folder outside the web root). The plugin warns you until the check passes.
Can customers change options after adding to the cart?
Yes, with the "Edit options" link on each cart line.
Where do I get help?
Email admin@007aj.com.
29. Changelog
0.5.4
- Fixed: live totals showed price format entities literally (for example "$ 5") with the "Left with space" and "Right with space" currency positions. The format, symbol and separators are now rendered as plain text.
- Fixed: role-based option prices are used in the live total too; the cart and the product page share one price resolver, and the page only carries the shopper's own prices.
- Fixed: on variable products the live total uses the selected variation's price, the same base the cart uses.
- Fixed: number and range fields enforce their step on the server (counted from the minimum, or 0).
- Fixed: option groups without fields are not shown, and the totals box only appears when there are fields.
- Fixed: PHP 8.4 str_getcsv() deprecation notice in the lookup table CSV import.
0.5.3
- Security: the public upload endpoint now has limits that a new session cannot reset: per guest IP address (hashed, IPv6 by /64), per session, per customer account, a store-wide hourly size cap and a cap on uploads waiting to be ordered. Counters are atomic; over a limit the response is HTTP 429 with Retry-After. All limits are in the settings.
- Security: every accepted format now has its own content check (images: signature, fileinfo type, decoding, dimensions, no code tags; PDF: header, %%EOF, fileinfo, no JavaScript, launch actions, embedded files or XFA; text: UTF-8, no NUL bytes, no HTML/PHP/script). The type filter can only remove formats.
- Uploads never ordered are now deleted hourly after 24 hours (was daily after 7 days); the settings screen shows pending upload storage.
0.5.2
- Wording: the option group and field limit notices and error messages now describe the limit itself and no longer mention another edition.
0.5.1
- New: the field editor can add and remove any number of conditions per field, with "all conditions match (AND)" or "any condition matches (OR)". Rules are stored in the same format as JSON import, reopen for editing exactly as saved, and nested condition groups from an import are kept. Rows have numbered labels for screen readers, work with the keyboard, announce additions and removals, and suggest the other field's choice values.
- Conditions are checked on save: a condition must point at another field of the same group.
- Fixed: a group assigned to a parent category now also applies to products that are only in one of its subcategories (any depth). Excludes work the same way.
- The category list on the group screen is shown as a tree (subcategories indented under their parent).
- Cached product lookups are cleared when a product category is added, moved or deleted, or when a product's categories or tags change.
- Developer: new filter
optionkit_match_child_categories(return false to match direct categories only, as before).
0.5.0
- New: Option analytics screen with most-picked options and choices, attachment rate, revenue from options and per-product average line value with and without options. Daily aggregate totals only (
okt_stats_daily), cancellation/refund reversal, retention setting with daily clean-up, rebuild from recent orders and reset; covered by the privacy eraser and policy text. - New: repeater field type (1–20 entries of up to 6 text, number or select sub-fields) with a "Per entry" price and free entries.
- New: upload folder status and "Check now" self-test, nginx rule in the settings, and an admin notice while the folder can be downloaded by direct URL.
- Accessibility: field labels and descriptions linked to inputs, radio groups and groups for choices, live totals announced after typing pauses, inline errors with focus on the first problem (layouts reveal the field first), keyboard tabs and accordion buttons, focus handling in steps and popup, visible focus outlines and reduced-motion support.
- Performance: upload/signature, layout and repeater scripts are separate files loaded only on products that use them; resolved option groups are cached between requests.
- Plugin Check: uploads use
wp_handle_upload(), exception messages are escaped, translator comments and input sanitizing added. - Fixed: the first request after activation could trigger a WordPress "translation loaded too early" notice; daily clean-up events are now scheduled on init.
- Required options are checked before the browser's own bubble appears, with the same inline message.
0.4.0
- New: lookup table pricing with CSV import (1–2 axes); live totals use the same tables.
- New: starter templates (engraving, gift wrap, pizza toppings, measurement), installed as new draft groups.
- New: importers with dry run for ThemeComplete EPO, PPOM and WooCommerce Product Add-Ons (merchant-owned data only).
- New: group layouts: steps, popup, accordion and tabs (plus stacked).
- New: first choices free, field/choice weight deltas for cart shipping, shipping hint text.
- New: role-based price amounts in the field editor.
- New: signature pad field (PNG through the secure upload system) and shortcode/HTML display field.
0.3.0
- New: formula prices and a Calculated fee field, evaluated by a built-in calculator (no code execution); the product page uses a JavaScript copy for live totals.
- New: swatches for dropdown, radio and checkbox fields (buttons, colors, images from the media library).
- New: file upload field with a type allowlist, image content checks, size limit, private storage, store manager downloads, daily clean-up of files never ordered, and personal data export/erasure support.
- New: edit a cart line's options from the classic cart or the Cart block.
- New: range slider and date picker fields with server-side checks.
- New: field Key for formulas; text max length; number min/max/step in the field editor.
- Products with only a calculated fee are charged correctly.
0.2.1
- Security: option selections are checked against the product's own fields before they reach the cart or the order; unknown keys, invalid choices and values of hidden fields are dropped.
- Text length caps, line breaks kept in text areas, number min/max and checkbox min/max enforced on the server.
- Store API cart item extension registered correctly; currency symbol in the total box fixed; more than two choices per field; "Select options" in shop lists; personal data export and erasure for option values on orders.
0.2.0
- Option group editing, assignment, storefront fields and totals, server-side pricing, cart and order data, Store API extension and JSON import/export. No limit on groups or fields; AND/OR condition matching.
0.1.0 – 0.1.1
- Initial release scaffold: WooCommerce dependency check, HPOS and Cart/Checkout blocks declarations, option group tables shared with the free plugin, screens, opt-in uninstall clean-up, personal data hooks, translation template; code prefixes renamed for WordPress guidelines.
Support: admin@007aj.com · Privacy · Terms · 007aj.com