Informacje techniczne
Documentation E-Toolkit Promotions
Instructions, technical specifications and change history — always in line with the current version of the product.
Technical compliance
WordPress
From version 6.4
Tested up to 7.1WooCommerce
Minimum version not specified
PHP
From version 7.4
Knowledge base
Documentation
User Manual Set-up, operation and troubleshooting.
E-Toolkit Promotions — User Guide
Requirements
WooCommerce must be active. Editing promotions requires permission to manage WooCommerce and an active E-Toolkit license.
Quick start
- Open ET Promotions in WordPress.
- Click Add promotion or select a template.
- Under Basics, enter a name and optional description.
- Under Conditions, select languages, set the active period, and add conditions. No selected language means all store languages; no conditions means every cart.
- Under Benefit, add at least one discount or bonus.
- Save a draft or click Activate.
- Verify the result with a real test cart. A shorter guide is available under ET Promotions → Guide.
Statuses
- Draft — does not affect the cart.
- Active — runs when its conditions and schedule match.
- Paused — remains stored but does not run.
Promotion list
The list shows 20 items per page. It orders active, scheduled, paused, and draft promotions first by status, then by recent modification. This affects only the dashboard; calculation order still follows rule priority.
Select an Active, Draft, or Paused counter to filter the table. Search checks names and descriptions across all promotions. Checkboxes activate, pause, or delete selected items on the current page. Bulk activation stops before making changes if any selected promotion is incomplete.
Conditions
A rule can check subtotal, total quantity, distinct line count, weight, first order, purchase history, customer or email domain, login and role, product, category, tag, brand, SKU, attribute, shipping and billing addresses, payment or shipping method, coupon, sale status, stock, and backorders. No conditions means every cart matches.
For multiple conditions, require all or any. Add condition group combines conditions with All (AND) or Any (OR) and can exclude the whole group, for example: “country is Poland AND (customer is a wholesaler OR previously bought the product).” One subgroup level keeps configuration readable.
Each card heading summarizes its condition, for example Cart total ≥ EUR 100. Conditions and groups can be collapsed, and a plain-language interpretation of the complete rule appears below the section.
When ET Lingua is active, product, category, and tag conditions include connected language versions. Under Promotion languages, select one or more ET Lingua languages. No selection means all languages. A rule limited to English will not run on the Polish storefront.
Purchase-history conditions use paid WooCommerce orders and apply to signed-in customers. Check the complete history or a selected period, last-order value and status, and order or item counts for products. For guests, numeric values are 0, lists are empty, and days-since-last-order does not match.
Lowest stock in cart considers only products and variations with WooCommerce stock management enabled. If none manage stock, the condition fails. Backordered product in cart means at least one line exceeds available stock and permits backorders.
Schedule
Start and end dates define the overall campaign period. An optional Recurring schedule limits weekdays and hours, such as Monday–Friday, 09:00–17:00.
Times use the WordPress timezone. A range can cross midnight, such as Friday 22:00–02:00. Equal start and end times mean the full selected day. Active-rule caching may delay storefront changes by up to one minute.
Actions
- percentage discount, up to 100%, optionally capped,
- fixed discount for the cart or each matching unit,
- fixed product price,
- free shipping,
- buy X, get Y for any cart products or selected products, categories, or tags,
- automatic existing WooCommerce coupon,
- quantity- or cart-value-based tiered discount,
- discount on a specified number of cheapest or most expensive units,
- product bundle using any products from a scope or one of each selected product, with a fixed price, percentage discount, or fixed discount.
Percentage, fixed, fixed-price, tiered, and bundle actions can target the cart, products or variations, categories, tags, brands, SKUs, attributes, or sale products. Specific products can be excluded. Configure global product, category, tag, and sale exclusions under Combination rules. Amounts use the WooCommerce currency.
For cheapest or most expensive items, configure unit count, percentage or fixed discount, and eligible products. A 100% discount makes those units free. The discount appears in cart totals and uses eligible product prices.
In Buy X, get Y, quantities of all products matching X are combined. X can also use brand, SKU, attribute, or sale status. Y can be free, percentage- or fixed-discounted, or have a fixed price. Add the first, cheapest, or most expensive item from a prepared pool, or let the customer choose. Choice works in classic Cart and Checkout and WooCommerce Blocks. The product is added only after selection and removed automatically if eligibility is lost.
Enable Y is the same product as X for “buy two, get a third of the same product free.” Each matching product or variation is counted separately, preventing an unrelated variation from being granted.
Select Y directly or by category or tag. A variable product expands to available purchasable variations. Customer choices are limited to 50 items for cart performance.
For Product bundle, “any products” selects a quantity from a scope, while “one of each product” creates a set from exact products. Apply a fixed bundle price, percentage, or fixed discount. Repeating bundles apply the benefit to each complete group.
Any-product bundles can have several tiers, such as 3 items for EUR 99 and 20% off from 5 items. The engine selects the highest matching tier and can repeat it for complete groups. When the product offer is visible, customers see these tiers in a Bundle prices table.
Repeat mode grants another Y for every multiple of X, such as X = 2 at quantities 4, 6, and 8. Without it, Y is granted only once regardless of excess X items.
Promotion visibility
Under Limits, independently configure:
- the applied-promotion message in classic Cart and Checkout and their blocks,
- product-page offer card,
- yellow badge on product images,
- countdown to the promotion end,
- progress toward the nearest amount or quantity tier,
- total savings after promotions,
- optional promotion-details modal shown beside a product and after adding it to the cart,
- promotion name and benefit in order emails.
Describe the key condition in offer text, such as “Buy at least 3.” Cards and badges appear only for products in the benefit scope; a cart-wide discount may appear on every product. A countdown requires an end date and hides automatically after expiry.
Under Storefront appearance, set message and badge colors and corner radius. The preview uses the same components as the store. Countdown text uses full day names, for example “2 days 06:05:34”.
Product discounts appear as a crossed-out regular price and a promotional price in the catalog and product page. Changing product-page quantity updates the price without a reload. Quantity discounts can show minimum and maximum unit prices from tiers. Price previews intentionally ignore conditions that cannot be resolved before the cart, such as shipping method or order history; the actual cart discount still applies.
Multilingual text
One promotion supports all languages by default. Do not duplicate a rule when only its text differs: conditions, benefits, schedule, and limits stay shared, preventing the discount from applying twice. Limit the rule under Conditions → Promotion languages only when the offer itself applies to selected storefronts.
After saving, open ET Lingua → String translations and select et-promotions-rules. Translate the name, description, cart and checkout message, product offer, badge, and progress message. Missing translations fall back to source text. Changing the WordPress UI language translates dashboard labels, not user-entered promotion content.
ET Lingua must remain active for language-limited promotions. If it is disabled, those rules stop running to avoid appearing in the wrong storefront. Rules without language restrictions continue normally.
Tiered promotions with Show offer on product page automatically display a tier table. Quantity tiers show required cart quantity and value tiers show required cart value. The table supports percentage and fixed discounts and variable products.
Free shipping uses an existing free-shipping method or adds a promotional zero-cost rate when none is available.
Quick test
Promotion test is separate from the summary. Its values simulate a cart and never change promotion settings. Add several lines with quantities and unit prices. Customer, shipping, and other fields appear when required by configured conditions or when expanded manually.
The result shows discount, amount due, and BOGO Y quantity. Diagnostics mark every condition and group as matched or unmatched and count issues. It also identifies limits, coupon conflicts, and missing benefits. Items in Promotion summary link to editor steps; an activation problem opens the correct step and focuses its first field.
Import and export
Export downloads rules as JSON. Import accepts up to 1 MB and 100 rules. Imported promotions are always drafts and must be reviewed before activation.
Order and limits
Rules run from highest to lowest priority; newer rules win ties. Exclusivity and stop-processing options end evaluation after the current rule.
Combination rules controls multiple matches: apply all, the first by order, or the one with the highest or lowest calculated discount. Free shipping, coupons, and gifts have comparison value 0. On a tie, the first rule wins.
When all promotions apply, choose whether every discount uses the original price — two 10% discounts equal 20% — or each subsequent discount uses the remaining amount, totaling 19%.
Discount price basis can use current cart price, regular price, active sale price, or the lowest available price. The default current cart price respects prices supplied by earlier WooCommerce integrations. ET Promotions never raises a better existing cart price. This applies to product and cart discounts, bundles, tiers, and paid BOGO gifts.
Calculate discount with tax controls amount conditions, fixed prices, and fixed discounts. Excluding tax retains standard WooCommerce behavior. Including tax calculates from the gross price and converts item discounts safely to the net price WooCommerce requires, keeping tax and totals consistent.
The same dialog controls customer coupons: combine them, prioritize the coupon, or prioritize promotions. Each promotion can override this choice. Coupons added automatically by ET Promotions are not customer coupons.
Global and per-customer limits use paid orders. Pending and failed orders do not consume limits. 0 means unlimited. Processing the same order again does not increment usage twice. Version 1.6.0 normalized any duplicate historical entries and prevents future double counting.
Reports and data
Reports cover 7, 30, 90, or 365 days. For each promotion they show order count, total and average order value, and total discounts in store currency. Summary reports load 20 promotions per page and use daily aggregates for predictable performance. Download current page CSV exports the visible rows.
Open one promotion's statistics through More actions (•••) → Promotion statistics. It shows order count, order value, average order value, and total discounts.
If one order uses several promotions, its value appears under each applied rule. Reports compare promotions; they do not calculate total store revenue. Deleting a rule removes its report events. Deactivation and uninstall preserve rules and reports.
WooCommerce order details include Applied ET Promotions, with rule names, discounts, free shipping, and gifts. The same data appears in HTML and plain-text WooCommerce emails unless disabled for a promotion. The order retains this snapshot after a rule is changed or deleted.
In Multisite, network activation prepares separate tables for each existing and future site.
The engine keeps active rules in a short cache and shares ET Lingua product mappings within one cart calculation. The release benchmark verifies 1,000 simultaneously matching promotions and rejects releases that exceed configured time or query limits.
Troubleshooting
- Confirm WooCommerce is active.
- Check the rule status and active period.
- Remember that higher priority runs first.
- Confirm products and coupons exist and are available.
- For gifts, check stock and purchasability.
- Test overlapping rules one at a time, starting with the highest priority.
Developer documentation Functions, hooks, filters and integration tips.
E-Toolkit Promotions — Developer Guide
This document describes only public functions, actions, and filters intended for theme or plugin integrations.
Public functions
etp_get_active_rules()
Returns active rules available in the current request language, with translated text and in execution order. Rules without a language scope are available in every language.
$rules = etp_get_active_rules();
foreach ($rules as $rule) {
$rule_id = (int) $rule['id'];
}etp_evaluate_simulation(array $context)
Calculates promotion results without changing the cart. The result includes applied, discount_total, cart_discount_total, item_discount_total, item_discounts, free_shipping, bogo, and coupons. To simulate several lines or BOGO, pass cart_items with separate cart_key, product_id, variation_id, quantity, and unit_price values.
$result = etp_evaluate_simulation([
'subtotal' => 250,
'item_qty' => 3,
'line_count' => 2,
'product_ids' => [123, 456],
'category_ids' => [12],
'tag_ids' => [18],
'brand_ids' => [24],
'sku_values' => ['SKU-123'],
'attribute_values' => ['pa_color:red'],
'user_logged_in' => true,
'user_id' => get_current_user_id(),
'user_roles' => ['customer'],
'customer_order_count' => 4,
'customer_history_periods' => [30 => ['order_count' => 2, 'total_spent' => 400]],
'last_order_amount' => 250,
'last_order_status' => 'processing',
'shipping_country' => 'US',
'shipping_state' => 'CA',
'shipping_city' => 'Los Angeles',
'shipping_postcode' => '90001',
'billing_country' => 'US',
'billing_state' => 'CA',
'billing_city' => 'Los Angeles',
'billing_postcode' => '90001',
'customer_ids' => [get_current_user_id()],
'customer_email_domain' => 'example.com',
'cart_weight' => 2.5,
'payment_method' => 'bacs',
'shipping_methods' => ['flat_rate:1'],
'coupon_codes' => ['welcome'],
'cart_items' => [
['cart_key' => 'example', 'product_id' => 123, 'quantity' => 2, 'unit_price' => 50],
],
]);etp_flush_active_rules_cache()
Clears the active-rule cache after data changes made outside the dashboard or public plugin REST API.
etp_flush_active_rules_cache();Filters
etp_product_price_basis
Changes a product's base price before promotion calculation. It receives the calculated basis, WC_Product, current cart price, and current, regular, sale, or lowest mode. The return value is clamped to a non-negative number.
add_filter('etp_product_price_basis', function ($price, $product, $current_price, $mode) {
if ($product->get_sku() === 'SPECIAL-SKU') {
return $current_price;
}
return $price;
}, 10, 4);etp_cart_context
Extends context before cart rules are evaluated. CRM integrations can provide customer_total_spent, customer_history_periods, customer_product_history, last_order_amount, last_order_status, days_since_last_order, and customer_purchased_product_ids. A null days_since_last_order means there is no previous order.
add_filter('etp_cart_context', function (array $context, WC_Cart $cart) {
$context['user_roles'][] = 'partner';
return $context;
}, 10, 2);Rule matching and selection
add_filter('etp_rule_condition_match', function (bool $matched, array $rule, array $context) {
return (int) $rule['id'] === 123 && !empty($context['user_id']) ? true : $matched;
}, 10, 3);
add_filter('etp_rule_actions_result', function (array $result, array $rule, array $context) {
$result['discount'] = min((float) $result['discount'], 100.0);
return $result;
}, 10, 3);
add_filter('etp_rule_selection_strategy', function (string $strategy, array $matches, array $context) {
return !empty($context['user_roles']) && in_array('wholesale_customer', $context['user_roles'], true)
? 'highest_discount'
: $strategy;
}, 10, 3);etp_rule_actions_result integrations should preserve cart_discount, item_discount, and item_discounts. etp_rule_selection_strategy must return all, first, highest_discount, or lowest_discount.
etp_cart_evaluation_result
Changes the shared result used by discounts, gifts, automatic coupons, and free shipping.
add_filter('etp_cart_evaluation_result', function (array $result, WC_Cart $cart) {
if ($cart->is_empty()) {
$result['discount_total'] = 0;
$result['cart_discount_total'] = 0;
$result['item_discount_total'] = 0;
$result['item_discounts'] = [];
}
return $result;
}, 10, 2);Labels and gift removal
add_filter('etp_discount_fee_label', function (string $label, array $result, WC_Cart $cart) {
return __('Partner program discount', 'my-plugin');
}, 10, 3);
add_filter('etp_lock_gift_removal', function (bool $locked, array $cart_item) {
return $locked;
}, 10, 2);
add_filter('etp_free_shipping_label', function (string $label) {
return __('Free promotional shipping', 'my-plugin');
});Storefront offers and price previews
etp_storefront_product_offers changes up to three offers prepared for a product. Each entry contains rule_id, name, message, show_message, badge, show_badge, show_modal, modal_message, ends_at, and style. style contains saved colors and corner radii.
add_filter('etp_storefront_product_offers', function (array $offers, WC_Product $product) {
return $product->is_in_stock() ? $offers : [];
}, 10, 2);etp_storefront_product_price_preview changes the public unit-price preview used in catalogs, product pages, and quantity updates. Preserve discounted, regular_price, promotional_price, price_html, and range_html.
add_filter('etp_storefront_product_price_preview', function (array $preview, WC_Product $product, int $quantity) {
if ($product->get_sku() === 'NO-PREVIEW') {
$preview['discounted'] = false;
$preview['price_html'] = wc_price(wc_get_price_to_display($product));
}
return $preview;
}, 10, 3);
add_filter('etp_storefront_badge_text', function (string $label, array $offer, WC_Product $product) {
return $product->is_featured() ? __('Special offer', 'my-plugin') : $label;
}, 10, 3);
add_filter('etp_storefront_product_tier_tables', function (array $tables, WC_Product $product) {
return $product->is_virtual() ? [] : $tables;
}, 10, 2);Tier-table entries use kind equal to tiered or bundle.
When E-Toolkit Product Search is active, promotion badges and storefront assets are added automatically to both its WooCommerce cards and built-in cards. A custom theme card can expose the same integration point by calling do_action('et_product_search_card_media_before', $product_id, $data, $context) inside its media area.
Brands and BOGO products
etp_product_brand_taxonomies sets brand-taxonomy order. The first existing taxonomy is used for brand conditions and dashboard search. Defaults are product_brand, pwb-brand, and yith_product_brand.
add_filter('etp_product_brand_taxonomies', function (array $taxonomies) {
return ['my_product_brand'];
});etp_bogo_reward_product_ids changes the list of available, purchasable Y products or variations after product, category, or tag resolution. The list is limited to 50 items.
add_filter('etp_bogo_reward_product_ids', function (array $product_ids, array $action) {
return array_values(array_filter($product_ids, function ($product_id) {
return !get_post_meta((int) $product_id, '_exclude_from_gifts', true);
}));
}, 10, 2);Actions
etp_after_apply_cart_discounts runs after the promotion result is applied to the cart:
add_action('etp_after_apply_cart_discounts', function (array $result, WC_Cart $cart) {
do_action('my_plugin_promotions_applied', $result['applied'], $cart);
}, 10, 2);Integration rules
- Result filters must always return arrays.
- Do not modify gift line items during an active cart recalculation.
- Product and term IDs include connected ET Lingua versions when ET Lingua is active.
- Cart data is available under
extensions.et-promotionsin the WooCommerce Store API response:messages,progress_message,savings_message, andgift_choices. The built-in integration displays it throughExperimentalOrderMetain Cart and Checkout Blocks. - Call
etp_flush_active_rules_cache()after changing rules externally.