Xania Code · Premium WooCommerce Plugin

WooCommerce Offer
Pricing Pro

A complete price negotiation system for your WooCommerce store. Customers propose a price, you control everything from the dashboard: accept, reject, or counter-offer every proposal.

WooCommerce 7.0+ WordPress 6.0+ PHP 8.1+ HPOS Compatible

📦 Overview

What this plugin does and how it integrates with WooCommerce

WooCommerce Offer Pricing Pro adds a complete "Make an Offer" system to any WooCommerce store. Customers see a form on the product page where they can suggest a custom price. The administrator receives offers in real time and can accept, reject, or counter-offer them directly from the admin panel.

The plugin works with both simple products and variable products. It supports auto-acceptance thresholds, configurable limits per product and per variation, CSV export, a dashboard widget, and a dedicated tab in the customer's "My Account" section.

ℹ️
Automatic 14-day Trial Upon first activation, the plugin automatically starts a 14-day trial. No license key is required to test. After the trial expires, the offer form is disabled until a valid license is entered — data and admin panels remain fully accessible.

Features

All capabilities included in version 1.0.0

🖥️ Server Requirements

Minimum and recommended configuration for optimal operation

Component Minimum Recommended Notes
WordPress 6.0 6.7+ Tested up to 6.9
WooCommerce 7.0 9.0+ Tested with 10.7
PHP 8.1 8.2 / 8.3 Uses: typed properties, named args, fibers-ready
MySQL / MariaDB MySQL 5.7 / MariaDB 10.3 MySQL 8.0+ / MariaDB 10.6+ Requires DECIMAL(19,4), ON UPDATE CURRENT_TIMESTAMP support
PHP Extensions openssl, mbstring, json Idem openssl required for AES-256 + HMAC licensing
wp-cron Enabled or server cron Server cron (more reliable) Required for offer expiration (wop_expire_offers_cron — hourly)
HTTPS Recommended Mandatory HMAC-signed links are secure only over HTTPS
Memorie PHP 128 MB 256 MB+ License Manager and Analytics graphics use more memory
Browser Chrome, Firefox, Edge, Safari, Opera Frontend fully responsive, JS ES2017+
⚠️
PHP 8.0 and older versions are not supported. The plugin uses PHP 8.1 syntax (intersection types, internal enums, named arguments). Activating on PHP 7.x or 8.0 will immediately throw a fatal error.

Checking PHP Extensions

Run via SSH or temporarily add to wp-config.php:

Shell
php -m | grep -E "openssl|mbstring|json"
PHP inline
<?php
echo extension_loaded('openssl') ? 'openssl: OK' : 'openssl: MISSING';
echo extension_loaded('mbstring') ? ' | mbstring: OK' : ' | mbstring: MISSING';
echo extension_loaded('json') ? ' | json: OK' : ' | json: MISSING';

🗄️ Database Structure

The plugin creates a single dedicated table upon activation: {prefix}wop_offers

Column Type Description
idBIGINT UNSIGNED PKUnique auto-increment ID
user_idBIGINT UNSIGNED0 for guests; WP user ID
product_idBIGINT UNSIGNEDWooCommerce product ID
variation_idBIGINT UNSIGNED0 if not a variation
quantityINTOffered quantity
offer_priceDECIMAL(19,4)Price proposed by the customer
counter_priceDECIMAL(19,4) NULLCounter price proposed by admin
original_priceDECIMAL(19,4)Catalog price at the time of the offer
currencyVARCHAR(10)ISO currency code (e.g. USD, EUR)
statusVARCHAR(20)pending / accepted / rejected / countered / expired / converted
noteTEXT NULLCustomer note when submitting the offer
admin_noteTEXT NULLInternal admin note
order_idBIGINT NULLPopulated after "Add to Cart" + order conversion
expires_atDATETIME NULLNULL if no expiry is configured
created_atDATETIMECreation timestamp (UTC)
updated_atDATETIMEAutomatically updated on any change

Automatically created indexes: idx_user, idx_product, idx_status, idx_expires, idx_order

🚀 Plugin Installation

Two methods: via the WordPress interface or manually via FTP/SSH

Method 1 — Upload via WordPress Interface (recommended)

  1. 1
    Go to Plugins → Add New → Upload Plugin

    From the WordPress admin menu, navigate to Plugins → Add New Plugin, then click the Upload Plugin button in the top right corner.

  2. 2
    Select the ZIP file

    Choose the file woocommerce-offer-pricing-pro-1_0_0.zip from your computer and click Install Now.

  3. 3
    Activate the plugin

    After installation, click Activate Plugin. The plugin will automatically create the wop_offers table in the database and set default values.

  4. 4
    Confirm the trial notification

    You will see an admin banner confirming the start of the 14-day trial period. No action is required — the plugin works immediately.

Method 2 — Manual FTP/SSH Upload

  1. 1
    Extract the ZIP locally

    Extract the contents — you will get the folder woocommerce-offer-pricing-pro/.

  2. 2
    Upload the folder to the server

    Transfer the folder via FTP/SFTP/SSH to the /wp-content/plugins/ directory.

  3. 3
    Activate from WP Admin

    Go to Plugins → Installed Plugins, locate WooCommerce Offer Pricing Pro and click Activate.

Quick post-installation check Go to WooCommerce → Offer Settings. If the page loads without errors and you see the configuration fields, the installation was successful.
⚠️
WooCommerce must be active The plugin checks at load time whether the WooCommerce class exists. If WooCommerce is inactive, an admin notice is displayed and frontend features are not initialized. The license page remains accessible.

🔑 License Activation

License management via the Xania Code License Manager

  1. 1
    Go to WooCommerce → Offer License

    The submenu appears automatically in the WooCommerce menu after activating the plugin.

  2. 2
    Enter the license key

    Paste the key received after purchase from xaniacode.com into the "License Key" field and click Activate.

  3. 3
    Activation confirmation

    The xaniacode.com server validates the key. On success, the page displays the "Active" status and expiry date. The key is stored encrypted (AES-256-CBC + HMAC).

🟡 Trial (14 days)

Started automatically on activation. The offer form works fully. No card or key required.

🟢 Licensed

All features activated. Auto-update available directly from the WP plugins panel.

🔴 Expired / No license

The frontend form is disabled. Admin remains accessible. Data is intact.

🔁 Auto-update

Update notifications appear in the WordPress plugins list. Updating is done with a single click, just like any other plugin.

🔒
Activation security Rate limiting at 5 attempts / 15 minutes on license activation. Error messages are generic to prevent key status enumeration.

⚙️ General Settings

WooCommerce → Offer Settings → General section

Option Type Default Description
wop_enable_globally Checkbox Yes Master switch — disabling immediately hides the form from all products.
wop_guest_offers Checkbox No Allows guests (non-logged-in users) to submit offers. If off, a login message is displayed.
wop_offer_expiry_days Number 7 Pending offers expire after this period. 0 = no expiry.
wop_min_offer_percent Number (0–100) 0 Global minimum offer as % of the displayed price. 0 = disabled. Overridable per product.
wop_auto_accept_percent Number (0–100) 0 Offers ≥ this % of the displayed price are automatically accepted. 0 = disabled.
wop_button_label Text Make an Offer The button text on the product page.
wop_success_message Textarea Your offer has been submitted… Message displayed to the customer after a successful submission.
wop_terms_text Text (empty) Label for the Terms & Conditions checkbox. If empty, the checkbox does not appear.
wop_terms_url URL (empty) Link opened when clicking the T&C label.

🛡️ Security & Limits

WooCommerce → Offer Settings → Security & Limits section

Option Type Default Description
wop_max_offers_per_product Number 3 Maximum number of active (non-rejected, non-expired) offers a customer can submit per product. 0 = unlimited.
wop_rate_limit_count Number 5 Maximum number of submissions allowed in the time window. 0 = disabled.
wop_rate_limit_window Number (sec) 3600 Duration of the rate limiting window in seconds. Minimum 60. Default: 3600 (1 hour).

Built-in Security Mechanisms

🔐 HMAC SHA-256

All customer-facing links (accept counter, add to cart) are signed with HMAC SHA-256 tokens with scope and expiry.

👁️ Ownership check

A logged-in user cannot use another user's link, even if they know the URL.

🔒 WP Nonce

All admin POST and AJAX actions use WordPress nonces. Any request without a valid nonce is rejected.

📊 CSV safe

CSV export protected against CSV Injection: cells beginning with = + - @ \t \r are prefixed with '.

🌐 Trusted Proxy IP

Client IP is correctly resolved behind proxies, checking forwarded headers only when REMOTE_ADDR is private/reserved.

🔑 Capability checks

All admin pages and actions verify the manage_woocommerce capability.

🎨 Visual Themes

WooCommerce → Offer Settings → Appearance section

The plugin includes 6 frontend themes based on CSS variables (--wop-*). The theme applies to the offer form and the My Account tab.

🔗
Inherit Inherits the active WordPress theme style. The form integrates visually seamlessly.
☀️
Light White background, WooCommerce purple accent, subtle borders.
🌙
Dark Dark background interface, suitable for dark-mode sites.
💼
Professional Navy gradient, elegant corporate look.
🌸
Art Floral Warm tones, ivory and rose, rounded corners, boutique style.
🖌️
Custom WordPress color picker (Iris) for a fully customized palette.

Custom Theme Colors

When the Custom theme is selected, the Custom Theme Colors section appears with 6 color picker fields:

OptionDefaultRole
wop_custom_bg#ffffffForm card background
wop_custom_bg2#f7f6fbSecondary background (form interior)
wop_custom_border#e2dff0Card and input borders
wop_custom_accent#7f54b3Primary color (button, focus, links)
wop_custom_text#1a1a2ePrimary text color
wop_custom_muted#6b6880Secondary text (hints, labels)
💡
The hover color and text contrast on the accent button are automatically calculated based on the chosen accent color luminance — no manual configuration needed.

📧 Email Notifications

WooCommerce → Offer Settings → Email Notifications section

OptionDefaultDescription
wop_notify_admin_email WP admin email Administrator email addresses. Separate multiple addresses with a comma.
wop_notify_admin_new Yes Sends an admin email for every new offer received.
wop_notify_customer_update Yes Sends an email to the customer when the offer is accepted, rejected, or counter-offered.

Automatically Sent Emails

🏷️ Per-Product Configuration

Individual product-level settings, from the WooCommerce product editor

In the editor of any WooCommerce product, under Product data → Pricing, a new Offer Pricing subsection appears with the following fields:

FieldDescription
Enable Make an Offer Per-product checkbox. If the global switch is off, this field has no effect.
Minimum Offer Price Minimum accepted amount for offers on this product (overrides the global percentage if set).
Maximum Offer Price Maximum amount — offers above this value are automatically rejected (rarely used).

Variable Products

For each variation, the same Min Offer Price and Max Offer Price fields appear. The frontend form dynamically updates limits when the customer changes the selected variation.

💡
Per-variation limits take priority over per-product limits, which take priority over the global percentage setting in Offer Settings.

📊 Admin Dashboard

WooCommerce → Offers — complete list of offers

The main admin page displays all offers organized by status tabs:

Available Actions per Offer

✅ Accept

Marks the offer as accepted and sends the customer an email with the signed "Add to Cart" link.

❌ Reject

Rejects the offer and (if enabled) sends a notification email to the customer.

↩️ Counter

Proposes an alternative price. The customer receives an email with a signed link for direct acceptance.

📋 Details

Detailed offer page with status history, admin notes and all customer data.

Bulk Actions

Select multiple offers (checkbox) and apply from the dropdown: Bulk Accept or Bulk Reject. Emails are sent individually for each offer.

CSV Export

The Export CSV button in the corner of the page exports any filtered view (tab + active filters). Exported columns include ID, product, variation, customer, offered price, catalog price, status, date.

WordPress Dashboard Widget

A widget automatically appears on the main WordPress Dashboard screen with KPIs from the last 30 days: total offers, accepted, rejected, conversion rate, and a direct shortcut to Pending offers.

🔄 Offer Flow

From customer submission to order conversion

  1. 1
    Customer — submits the offer

    On the product page, the customer enters the desired price and clicks "Make an Offer". The form is submitted via AJAX (no page reload). The value is validated server-side (min/max, rate limit, nonce).

  2. 2
    Server — checks auto-accept

    If wop_auto_accept_percent > 0 and the price ≥ threshold, the offer is automatically accepted and the acceptance email is sent immediately. Otherwise, status remains pending.

  3. 3
    Admin — notified by email

    If wop_notify_admin_new = yes, the administrator receives an email with offer details and a direct link to the admin detail page.

  4. 4
    Admin — acts on the offer

    From the dashboard, the administrator chooses: Accept, Reject or Counter (with an alternative price).

  5. 5
    Customer — receives status email

    On accept: receives a signed "Add to Cart" link. On counter: receives a signed counter-offer acceptance link. On reject: receives a notification.

  6. 6
    Customer — adds to cart and checks out

    Via the link in the email or from the "My Offers" tab, the customer adds the product at the negotiated price to the cart and completes the order normally through WooCommerce.

  7. 7
    System — marks as "Converted"

    When the order is created, the offer is marked converted and order_id is saved in the table.

↩️ Counter-Offers

Two-way negotiation between admin and customer

The Counter-Offer feature allows the administrator to propose a different price from the customer's offer, without directly accepting or rejecting it.

How it works

  1. 1
    Admin enters the counter price

    On the offer details page, the administrator fills in the Counter Price field and clicks Send Counter Offer.

  2. 2
    Customer receives the email

    The email contains the customer's original price, the counter price proposed by the admin, and an accept button with a signed HMAC link.

  3. 3
    Customer accepts the counter

    By clicking the button (or from the My Offers tab), the offer moves to accepted status at the counter price. The admin receives a confirmation notification.

🔐
Counter token security The HMAC token is bound to (offer_id, user_id, status=countered, action=accept_counter, expiry). It cannot be reused, cannot be used by another user, and does not work after expiry.

📈 Analytics

WooCommerce → Offer Analytics

📊 Global KPIs

Total offers, accepted offers, conversion rate, average percentage vs catalog price.

🥧 Status Breakdown

Distribution by status: pending, accepted, rejected, countered, expired, converted.

🏆 Top Products

Most offered products, with number of offers and conversion rate.

📅 Daily Trend

Chart showing daily evolution of offers received over a selectable period.

The Export CSV button on the Analytics page exports filtered data for processing in Excel or other tools.

👤 My Account — My Offers

Customer experience after submitting offers

Logged-in customers see an additional My Offers tab on the WooCommerce My Account page. The tab displays all submitted offers with their current status.

For offers with Accepted or Counter Accepted status, the Add to Cart at Offer Price button appears, adding the product to the cart at the negotiated price with a single click, using a secure signed link.

💡
Guests who have submitted offers (if guest offers is enabled) can check the status of their offers via the links in the confirmation email. The My Account tab is only available to logged-in users.

🗑️ Uninstall

How cleanup works when deleting the plugin

⚠️
Default behavior: data is RETAINED Deleting the plugin from the plugins list does not delete the wop_offers table or the wop_* settings. Reinstalling will find all data intact.

Full Deletion (irreversible)

If you want a complete cleanup on uninstall:

  1. 1
    Enable the option in settings

    Go to WooCommerce → Offer Settings → Uninstall and check Delete data on uninstall, then save.

  2. 2
    Delete the plugin

    From Plugins → Installed Plugins, deactivate the plugin and then click Delete.

The uninstall script will delete: the {prefix}wop_offers table, all wop_* options, all per-product metadata, all per-order-item metadata, and the license status.

🚨
Irreversible action Once deleted, data cannot be recovered without a backup. Make sure you have a database backup before enabling this option.

🔧 Troubleshooting

Common issues and their solutions

1 The "Make an Offer" form does not appear on the product page.
Check:
  1. WooCommerce → Offer Settings → Enable offer system is checked (master switch).
  2. On the product, under Product data → Pricing → Enable Make an Offer is checked.
  3. The plugin is activated and WooCommerce is active.
  4. The trial or license has not expired (check WooCommerce → Offer License).
  5. The WordPress theme does not override WooCommerce hooks — test with Storefront or Twenty Twenty-Four.
2 Expired offers do not disappear / cron is not working.
The plugin uses wp-cron for hourly expiration (wop_expire_offers_cron). If the site has low traffic, wp-cron may not execute frequently enough.

Recommended solution: disable wp-cron in wp-config.php and configure a real server cron:
# În wp-config.php
define('DISABLE_WP_CRON', true);

# Server cron (cPanel / SSH) — every 15 minutes
*/15 * * * * wget -q -O - https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
3 Emails are not being sent to customers or admins.
  1. Check that wop_notify_admin_new and wop_notify_customer_update are enabled in Offer Settings → Email.
  2. Check the admin address configured in wop_notify_admin_email.
  3. WordPress sends emails via PHP mail() by default — use an SMTP plugin (e.g. WP Mail SMTP) for reliable delivery.
  4. Check the recipient's Spam folder.
  5. Test with WP Mail SMTP → Email Test.
4 "Invalid token" error when clicking the link in the email.
All customer action links (accept, add to cart) are HMAC-signed with expiry. The token may be invalid if:
  • The link has expired (check wop_offer_expiry_days).
  • The offer status has changed (e.g. admin rejected it in the meantime).
  • The URL was modified / truncated by the email client — ensure emails are sent in HTML format.
  • The customer is logged in with a different account than the one that submitted the offer.
5 Fatal PHP error upon activation.
The most likely cause is an incompatible PHP version. Check the PHP version under Tools → Site Health → Info → Server → PHP Version. It must be 8.1 or higher.

If PHP is 8.1+ and the error persists, verify the openssl extension is active:
php -m | grep openssl
6 The submit button shows both the text and spinner simultaneously.
This is an issue resolved in version 1.0.0. The cause was that the CSS class .wop-btn-spinner { display: inline-flex } overrode the HTML5 [hidden] attribute. The fix is already implemented via the rule .wop-offer-form [hidden] { display: none !important }. If you see this issue, clear the site's CSS cache.
7 The wp_wop_offers table does not exist in the database.
The table is created upon plugin activation via the register_activation_hook hook. If it was skipped (e.g. FTP upload without admin activation):
  1. Deactivate the plugin from admin.
  2. Reactivate it — activation will run WOP_Activator::activate() and create the table via dbDelta().
8 License activation fails with a generic error.
The system intentionally displays generic messages to avoid revealing key status. Check:
  • The server can make outbound requests to https://xaniacode.com (check firewall / WAF).
  • You have not exceeded the license activation limit (check your account on xaniacode.com).
  • You have not hit the rate limit of 5 attempts / 15 min — wait and try again.
  • The key has not expired and is correct (no extra spaces when pasting).
9 Custom theme settings are not saving correctly / colors do not appear.
  • Make sure you have selected the Custom theme in the Appearance dropdown — the Custom Theme Colors section only appears for this theme.
  • Clear the cache plugin's cache (WP Rocket, W3TC, LiteSpeed etc.) after saving settings.
  • Verify that JavaScript is enabled — the Iris color picker requires JS.

📋 Changelog

Version history

v1.0.0 April 28, 2026 — First public release

Added

  • Make an Offer form on the product page (simple + variable, min/max per variation)
  • Admin dashboard: tabbed lists, offer details, bulk accept/reject, CSV export
  • Counter-offer with signed HMAC tokens for customer acceptance
  • Auto-accept threshold (% of catalog price)
  • "My Offers" tab in WooCommerce My Account with one-click Add-to-cart
  • Analytics page: KPIs, status breakdown, top products, daily trend
  • Dashboard widget with 30-day KPIs
  • 6 frontend themes (Inherit / Light / Dark / Professional / Art Floral / Custom)
  • Custom theme with WordPress color picker (Iris) for a full palette
  • Admin and customer email notifications
  • Rate limiting per user / per IP, configurable from settings
  • Offer cap per customer per product
  • Declared HPOS compatibility
  • Xania Code License Manager v2.1.1 (14-day trial, auto-update)
  • Uninstall script with optional cleanup (opt-in)

Fixed

  • Submit button was showing both the label and spinner simultaneously (fix: [hidden] { display:none !important } defender)

Security

  • HMAC SHA-256 tokens on all customer URLs
  • Server-side ownership check on token actions
  • Encrypted license key storage (AES-256-CBC + HMAC)
  • Rate limiting on license activation (5 / 15 min)
  • Nonce verification on all admin and AJAX POSTs
  • CSV injection mitigation
  • Trusted-proxy-aware IP resolution
  • wp_safe_redirect on all cart redirects