Skip to main content

Dynamic Pricing

Overview​

Dynamic Pricing is one of the seven modules in the free core. It applies rules that change what a customer pays, in three distinct ways: adjusting a product's price, applying a cart-level discount, or adding a free gift to the cart when the rule's conditions are met.

The three are genuinely different mechanisms. A product-price rule filters WooCommerce's price getters, so the new price appears everywhere a price is shown — the shop loop, the product page, variation prices, the cart line. A cart discount is a negative fee on the cart totals. A gift rule puts a product in the cart and keeps it there on the module's terms, not the customer's.

It is the free core's pricing engine, and it is available on every plan.

Availability​

ItemValue
Module keydynamic_pricing
TierFree — part of the free core
Entitlement keydynamic_pricing
Admin tabdynamic-pricing
Enabled optionaiowc_module_enabled_dynamic_pricing (off until turned on)
REST namespaceaiowc/v1

Enabling the module creates the two tables below and schedules the cleanup job.

registerHooks() performs no licence check of its own and reads no enable setting — it registers the REST routes, the three appliers, the frontend handlers and the job listener unconditionally. Being free-tier, the entitlement gate grants it on every plan anyway.

Settings​

This module has no settings row. It declares no settings prefix and no defaults. Everything is expressed per rule, which is why the rule row carries its own exclusivity, sale-item and usage-limit fields rather than reading them from a shared setting.

Rule types​

rule_typeWhat it does
product_priceChanges a product's price, through WooCommerce's price filters.
cart_discountApplies a discount to the cart as a negative fee.
free_giftAdds a product to the cart at no charge when the conditions hold.
discount_typeMeaning
percentageA percentage off.
fixedA fixed amount off.
fixed_productA fixed price for the product, rather than an amount off.

A rule's status is active, draft, scheduled or expired, and the cleanup job moves rules past their end date to expired.

Rules​

FieldMeaning
conditionsWhen the rule applies, stored as JSON.
discount_configWhat it does when it applies, stored as JSON.
priorityWhich rule wins when several match.
start_date, end_dateThe window the rule is live in.
usage_limitHow many times the rule may be used in total.
usage_limit_per_userHow many times one customer may use it.
is_exclusiveWhen set, this rule applies alone and no other stacks with it.
exclude_sale_itemsLeaves products already on sale alone.
created_byThe administrator who created the rule.

Every application is recorded in the usage table with the rule, order, customer and the amount discounted, which is both how the limits are enforced and what the per-rule statistics count.

Free gifts​

A gift rule adds its product to the cart. The module owns that line: it overrides the line's price, name, quantity control and remove link, and reacts when the customer removes it or when the cart changes such that the rule no longer applies. That is why the module hooks so much of the cart item display — a gift the customer could re-price or keep after qualifying would not be a gift.

Conflicts between rules​

Several rules can match one product or cart. An exclusive rule wins alone; otherwise stacking is decided by the module's conflict resolver, and whether two particular rules may stack is passed through the aiowc_dynamic_pricing_can_stack_rules filter. A condition type the module does not recognise is passed to aiowc_dynamic_pricing_evaluate_condition, so a store can add its own without modifying the module.

Admin screen​

The Dynamic Pricing tab lists the rules with an overview of how many exist and how often they have applied, creates and edits them, duplicates one, deletes in bulk, and shows per-rule statistics. A preview endpoint prices a hypothetical rule before it is saved.

REST API endpoints​

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

MethodPathPurposeRequired args
GET/dynamic-pricing/rulesEvery rule.–
POST/dynamic-pricing/rulesCreate a rule.name, rule_type
GET/dynamic-pricing/rules/{id}One rule.id
PATCH / PUT /POST/dynamic-pricing/rules/{id}Update a rule. All three verbs are registered.id
DELETE/dynamic-pricing/rules/{id}Delete a rule.id
POST/dynamic-pricing/rules/{id}/duplicateCopy a rule.id
GET/dynamic-pricing/rules/{id}/statsHow often the rule has applied, and for how much.id
POST/dynamic-pricing/bulkApply an action to several rules at once.action, ids
GET/dynamic-pricing/overviewThe counts shown on the overview.–
POST/dynamic-pricing/previewPrice a rule without saving it.rule_type

Every route is administrator-only; the storefront gets its prices through WooCommerce's filters rather than by calling the API.

WooCommerce integration​

This module has the broadest hook surface of any pricing module, because changing a price convincingly means changing it everywhere it is displayed.

AreaHooks
Product pricewoocommerce_product_get_price, _get_regular_price, _get_sale_price, _is_on_sale, and the three matching product_variation_get_* filters, plus woocommerce_variation_prices_price
Price displaywoocommerce_get_price_html, woocommerce_after_shop_loop_item_title, woocommerce_single_product_summary
Cart totalswoocommerce_before_calculate_totals, woocommerce_cart_calculate_fees, woocommerce_cart_totals_before_order_total, woocommerce_review_order_before_order_total
Cart lineswoocommerce_cart_item_price, _subtotal, _name, _quantity, _remove_link, _removed
Cart lifecyclewoocommerce_add_to_cart, woocommerce_cart_updated, woocommerce_cart_loaded_from_session
Couponswoocommerce_applied_coupon, woocommerce_removed_coupon — so a rule can react to a coupon being used
Orderwoocommerce_checkout_create_order, woocommerce_checkout_order_processed, woocommerce_order_status_completed — recording usage
Order displaywoocommerce_order_details_after_order_table, woocommerce_admin_order_data_after_billing_address

Database schema​

TableHolds
{prefix}aiowc_pricing_rulesThe rule: name, slug, description, type, status, priority, conditions and discount configuration as JSON, date window, usage limits and count, exclusivity, sale-item exclusion, creator.
{prefix}aiowc_rule_usageOne row per application: the rule, order, customer and amount discounted.

aiowc_pricing_rules is this module's table. The premium Dynamic Pricing Rules module keeps its own under a dpr_ prefix, so the free and premium modules never share a row.

Background jobs​

HookWork
aiowc_dynamic_pricing_cleanupMarks rules past their end date as expired and prunes old usage rows.

The job runs on Action Scheduler.

Action hooks for integrators​

HookPurpose
aiowc_dynamic_pricing_evaluate_conditionFilter — evaluate a condition type the module does not know.
aiowc_dynamic_pricing_can_stack_rulesFilter — decide whether two matching rules may be combined.
aiowc_track_eventThe module is enabled or disabled.
aiowc_capture_errorAn error is caught while evaluating or applying a rule.

Entitlement limits​

dynamic_pricing is granted on every plan including the free one, with no cap on the number of rules. The usage limits are per-rule settings, not licence limits.

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​

  • Two modules filter woocommerce_product_get_price — this one and the premium Dynamic Pricing Rules. With both enabled, both adjust the same price and neither knows about the other, so the resulting price depends on filter order rather than on either module's conflict resolution. A store should run one or the other.
  • With no settings row there is no storefront kill switch: the module is either on with all of its hooks, or disabled entirely.
  • Rules are expired by a background job rather than checked at read time, so a rule can apply briefly past its end date until the job next runs.
  • The preview endpoint prices a rule in isolation; it does not show how the rule would interact with the others already active.