# Dynamic Pricing Engine — Complete guide

> Complete guide to the Dynamic Pricing Engine plugin for WooCommerce: installation, configuration, 4 rule types (time, stock, segment, competitor), customer segments, competitor scraping, native A/B testing, log, 3-level safeguards, FAQ.

- Page: <https://www.datafirefly.com/en/documentation/dfdynamicpricing/>
- Language: en
- Last updated: 2026-07-01
- Other languages: [fr](https://www.datafirefly.com/documentation/dfdynamicpricing/index.md), [es](https://www.datafirefly.com/es/documentation/dfdynamicpricing/index.md), [de](https://www.datafirefly.com/de/documentation/dfdynamicpricing/index.md), [it](https://www.datafirefly.com/it/documentation/dfdynamicpricing/index.md), [pl](https://www.datafirefly.com/pl/documentation/dfdynamicpricing/index.md), [nl](https://www.datafirefly.com/nl/documentation/dfdynamicpricing/index.md), [pt](https://www.datafirefly.com/pt/documentation/dfdynamicpricing/index.md)
- Index: <https://www.datafirefly.com/en/documentation/llms.txt>

Welcome to the complete documentation for **Dynamic Pricing Engine**, the dynamic pricing engine for WooCommerce by DataFirefly. This guide covers installation, initial configuration, each rule type, customer segmentation, competitor scraping, A/B testing, logging, safeguards, and uninstallation.

**Requirements:** WordPress 6.0+, WooCommerce 8.0+, PHP 7.4+. HPOS and Checkout Blocks compatible.

## Installation

### Uploading the plugin

1. From the WordPress back-office, go to **Plugins → Add New → Upload Plugin**.
2. Select the `dfdynamicpricing.zip` file and click _Install Now_.
3. Once installation completes, click _Activate Plugin_.

### What happens on activation

The plugin creates 6 custom tables (prefixed `wp_dfdpe_`):

- `wp_dfdpe_rules` — pricing rules
- `wp_dfdpe_logs` — adjustment log
- `wp_dfdpe_segments` — customer segments (3 seeded automatically)
- `wp_dfdpe_competitors` — competitor tracking
- `wp_dfdpe_ab_tests` — A/B tests
- `wp_dfdpe_ab_events` — exposure, ATC, and conversion events

Two cron tasks are also scheduled: competitor scraping (hourly by default) and log purging (daily).

### Admin menu

A new **Dynamic Pricing** menu appears in the sidebar with 7 sub-menus: Dashboard, Rules, Segments, Competitors, A/B Testing, Log, Settings. All actions require the WordPress capability `manage_woocommerce`.

## Initial configuration (Settings)

Before creating your first rule, take a quick tour in **Dynamic Pricing → Settings** to adjust the global parameters.

### Log

- **Enable log**: checked by default. Every adjustment is recorded with product, rule, customer, context.
- **Retention (days)**: 60 days by default. Automatic purge runs daily.

The log is rate-limited to 1 entry per session, product, and hour to avoid flooding. You can disable it entirely if you don't use it.

### Global safeguards

- **Floor price (% of original price)**: e.g., 70 = never go below 70% of the original price. 0 = disabled.
- **Ceiling price (% of original price)**: e.g., 130 = never exceed 130%. 0 = disabled.
- **Never sell below cost of goods**: enable if you store the cost in a product meta.
- **Cost meta key**: `_cost` by default (compatible with WooCommerce Cost of Goods).

### Competitor scraper

- **Execution frequency**: hourly, twice daily, or daily. The scraper processes 25 URLs per batch.

### Front-office display

- **Show original price crossed out**: useful for a visible promo effect. Disable for confidential A/B tests.

## Creating your first rule

Go to **Dynamic Pricing → Rules → Add**. Each rule has the same base fields, regardless of its type.

### Common fields

- **Name**: internal label, useful in the log (e.g., "Happy hour 6pm-8pm").
- **Type**: Time, Stock, Customer Segment, or Competitor.
- **Status**: Active or Inactive. An inactive rule is never evaluated.
- **Priority**: rules execute in ascending priority order. Each rule works on the result of the previous one.
- **Scope**: Global, Category, Tag, or Specific product.
- **Adjustment**: Percentage, Fixed amount, Set value, or Competitor match (only with Competitor type).
- **Floor / Ceiling**: optional per-rule safeguards.
- **Date window**: start and end dates to activate the rule only during a given period.
- **A/B Test**: optional link to an A/B test and variant (see A/B Testing section).

**Prioritization tip:** start with broad (global) rules at low priority, then refine with targeted rules at higher priority. The global safeguards configured in Settings always apply last.

## Type 1 — Time rule

Adjusts the price based on the hour and day of the week. Ideal for happy hour, weekend promos, or night rates.

### Available conditions

- **Days of the week**: select one or more days (Monday to Sunday, ISO format).
- **Start hour / End hour**: 24h format. Ranges that cross midnight are handled automatically (e.g., 10pm-2am).
- **Timezone**: _site_ (default, uses the WordPress timezone) or a specific timezone (e.g., `Europe/Paris`).

### Concrete examples

- **Happy hour**: −15%, Thursday-Friday, 6pm-8pm, Europe/Paris timezone.
- **Weekend promo**: −10%, Saturday-Sunday, 00h-23h59.
- **Night pricing**: +5%, every day, 10pm-6am (crosses midnight, handled automatically).

## Type 2 — Stock rule

Adjusts the price based on the product stock level. Useful for quickly clearing overstocked products or premium-pricing scarce ones.

### Available conditions

- **Operator**: .
- **Threshold**: integer.
- **Mode**: _Absolute_ (number of units) or _Percentage of initial stock_ (requires the `_initial_stock` meta on the product).

### Concrete examples

- **Clearance**: stock >= 50 (overstock) → −20%.
- **Scarcity**: stock < 5 → +10%.
- **Initial stock percentage**: percentage mode, stock < 20% of initial stock → −5%.

To use Percentage mode, add an `_initial_stock` meta field to your products (via WP All Import, ACF, or a simple `update_post_meta`). Without this meta, percentage mode is ignored.

## Type 3 — Customer segment rule

Applies an adjustment only to customers belonging to one or more defined segments.

### Available conditions

- **Segments**: one or more existing segments (see Segments section).
- **Match**: _Any_ (customer belongs to at least one segment) or _All_ (belongs to all).

### Concrete examples

- **Loyalty**: _loyal-customers_ segment, −10% adjustment.
- **Win-back**: _dormant_ segment (to create), −20% adjustment for 7 days.
- **B2B**: _b2b_ segment (`wholesale` role), −25% adjustment.

## Type 4 — Competitor price rule

Aligns your price with a competitor you have configured in the Competitors section. Three strategies available.

### Strategies

- **Match**: your price becomes exactly the competitor's price.
- **Undercut**: your price drops below the competitor's, by percentage or fixed amount.
- **Overprice**: your price goes above the competitor's (premium positioning).

### Available conditions

- **Mode**: _Percentage_ or _Fixed amount_.
- **Amount**: percentage (e.g., 5 for 5%) or amount in currency.
- **Maximum data age (hours)**: beyond this, scraped data is considered too old and the rule switches to fallback behavior.
- **Fallback**: behavior when competitor data is unavailable (e.g., apply a neutral adjustment or skip the rule).

### Concrete example

Undercut 3% of Competitor A, with a 6-hour max age. If Competitor A hasn't been scraped in 6 hours, the rule is ignored and the price stays unchanged.

## Customer segments

A segment is a combination of criteria defining a group of customers. Once created, a segment can be targeted by a rule of type _Customer segment_.

### Segments seeded on activation

- **new-customers**: customers with 0 or 1 order.
- **loyal-customers**: customers with 5 or more orders.
- **vip**: customers who have spent at least €500.

### Creating a segment

From **Dynamic Pricing → Segments → Add**, define:

- **Name** and **Slug** (auto-generated if empty).
- **Description** (optional, for your team).
- **Criteria**: add as many rows as needed. All criteria must be satisfied (AND logic).
- **Status**: active or inactive.

### Available criteria fields

- `order_count` — customer's order count.
- `total_spent` — total spent (in the site currency).
- `is_guest` — 1 if visitor is not logged in, 0 otherwise.
- `user_roles` — customer's WordPress roles (e.g., `customer`, `subscriber`, `wholesale`).
- `days_since_last_order` — days since the last order.

### Available operators

Ten operators: `==`, `!=`, `>`, `>=`, `= 60`. Targets previous customers who haven't ordered in 2 months.

## Competitors (scraping)

The scraper automatically retrieves the price displayed on a competitor's product page, at a configurable frequency. Scraped prices are then used by rules of type _Competitor_.

### Adding a competitor

From **Dynamic Pricing → Competitors → Add**:

1. **WooCommerce product (ID)**: the local product ID to link the tracking to.
2. **Competitor name**: free label (e.g., "Amazon", "eBay").
3. **URL**: the competitor's product page to scrape.
4. **Selector type**: CSS, XPath, Regex, or JSON-LD.
5. **Selector**: the selector pointing to the price (see examples below).
6. **Currency**: defaults to the site's WooCommerce currency.
7. **Status**: active or paused tracking.

### Selector types

- **CSS**: classic CSS selector. Examples: `.price .amount`, `#product-price`, `span[itemprop=price]`.
- **XPath**: XPath expression. Example: `//span[@class="price"]`.
- **Regex**: PHP regular expression. Example: `/€s*([d,.]+)/` — the first captured group is used.
- **JSON-LD**: Schema.org auto-detection. Searches for `price`, `offers.price`, `offers.lowPrice` in JSON-LD tags. Leave the Selector field empty.

### Price parsing

The scraper handles European (`1 299.90`) and US (`1,299.90`) formats automatically. Currency symbols and spaces are cleaned up.

### Manual execution

The **Scrape now** button next to each competitor forces an immediate AJAX update. Useful for testing a new selector.

### Possible statuses

- **pending** — never scraped, waiting for next cron.
- **ok** — last run succeeded.
- **error** — last run failed (message stored in the _last_error_ field).

**Respect competitor T&Cs:** the scraper performs a simple HTTP request with a short timeout, but it's your responsibility to check that scraping is allowed by the target sites' Terms of Service. Some jurisdictions regulate this practice.

## A/B Testing

The built-in A/B module lets you compare multiple pricing strategies on the same product and measure their impact in real time (exposures, add-to-cart, conversions, RPV).

### Creating a test

From **Dynamic Pricing → A/B Testing → New test**:

1. **Name** and **slug**.
2. **Variants**: list of labels separated by commas. Default `A,B`.
3. **Traffic split**: relative weight per variant (auto-normalized). For example `50/50`, `70/30`, or `1/1/1` for three even variants.
4. **Status**: Draft, Running, Paused, or Completed. Only _Running_ tests assign visitors.
5. **Window**: optional start and end dates.

### Linking a rule to a variant

In the rule form, select the A/B test and the target variant. The rule will only apply to visitors assigned to that specific variant.

### How assignment works

On first exposure, the plugin assigns the visitor to a variant according to configured weights, then stores this choice in a `dfdpe_ab` cookie. A separate session cookie `dfdpe_sid` tracks the same visitor throughout their session, logged in or not.

### Tracked events

- **exposure** — first time the visitor sees a price affected by the test.
- **atc** — add to cart (`woocommerce_add_to_cart` hook).
- **conversion** — finalized order (`woocommerce_thankyou` hook). The order total is recorded.

### Calculated metrics (Results page)

- **Exposures** and **Unique sessions**.
- **ATC CR** — add-to-cart rate (ATC / exposures).
- **Conv. CR** — conversion rate (conversions / exposures).
- **Revenue** — total conversions.
- **RPV** — revenue per visitor (revenue / exposures). This is the key decision metric: the variant with the highest RPV is highlighted automatically (_Winner_ badge).

**Best practice:** let a test run for at least 2 weeks before concluding. A reliable A/B test requires several thousand exposures to reach statistical significance.

## Adjustment log

Every price adjustment applied on the front-office can be logged. The log is accessible via **Dynamic Pricing → Log**.

### Recorded information

- Date and time.
- Product and variation.
- Triggered rule (ID).
- Customer (ID) or anonymous session.
- Original price, final price, adjustment amount.
- A/B test and variant (if applicable).
- Context: `frontend`, `cart`, `checkout`.

### Available filters

You can filter by product ID, rule ID, or A/B test ID. Pagination shows 50 entries per page.

### Rate-limiting

To avoid flooding, the plugin limits recording to 1 entry per session, product, and hour. A session viewing the same product page 100 times within an hour generates only one row.

### Automatic purge

A daily cron task (`dfdpe_cron_purge_logs`) deletes entries older than the configured retention (60 days by default).

## Safeguards: how they work

Three successive levels of protection prevent your final price from reaching a dangerous level.

### Level 1 — Per-rule safeguards

Each rule can define its own floor and ceiling. They apply immediately after this rule's adjustment. Useful for capping the effects of a specific rule (e.g., "happy hour can never drop below €30, regardless of original price").

### Level 2 — Global safeguards

Defined in Settings, as a percentage of the original price:

- **Floor price**: the final price cannot drop below this percentage.
- **Ceiling price**: the final price cannot exceed this percentage.

Example: 70% floor and 130% ceiling. A €100 product can never drop below €70 nor exceed €130, whatever rules are applied.

### Level 3 — Cost-of-goods protection

If enabled in Settings, this protection prevents the final price from dropping below the value of the `_cost` meta (or the custom key you configure). This is the ultimate guarantee against selling at a loss.

The three levels are cumulative and apply in this order: rule → global → cost. The final price is always the most "protected" of the three results.

## HPOS and cache compatibility

### HPOS (High-Performance Order Storage)

The plugin declares compatibility with `custom_order_tables` and `cart_checkout_blocks` at initialization. No additional action is required if you have enabled HPOS in WooCommerce.

### Variation price cache

WooCommerce caches the min and max prices of variable products via a hash. The plugin injects a dynamic seed (user + session + 5-minute bucket) into this hash via the `woocommerce_get_variation_prices_hash` filter, forcing WooCommerce to recalculate prices at the right moment without breaking the cache for other visitors.

## FAQ

### Can I combine multiple rules on the same product?

Yes. Rules execute in priority order, each working on the previous one's result. You can chain "−10% VIP" then "cap at 130% of cost".

### Do rules apply to cart and checkout too?

Yes. A hook on `woocommerce_before_calculate_totals` recalculates cart line prices on every display.

### Is the plugin compatible with server caches (Redis, Varnish)?

Yes, but if your cache is very aggressive at the full-page level, displayed prices may be cached ones. For reliable dynamic display, exclude product pages from full-page cache, or use ESI fragments.

### Can I deactivate the plugin without losing my rules?

Yes. Deactivation does not delete any data. Only uninstalling via _Plugins → Delete_ triggers the `uninstall.php` script.

### How do I export my data?

All data is stored in the 6 `wp_dfdpe_*` tables. You can export them via phpMyAdmin, WP-CLI (`wp db export`), or any WordPress backup tool.

## Uninstalling

To completely uninstall:

1. Deactivate the plugin from **Plugins**.
2. Click _Delete_.

The `uninstall.php` script then removes:

- The 6 `wp_dfdpe_*` tables.
- The 9 WordPress options created.
- The scheduled cron tasks.

Uninstallation is definitive and non-reversible. Back up your rules, segments, and log first if you want to be able to roll back.

## Support

Your license includes 12 months of support and updates. For any question, contact us via [datafirefly.com/contact](https://www.datafirefly.com/contact/).
