Skip to main content

Rewards & Points

Overview​

Rewards & Points gives customers points for what they do — buying, signing up, leaving a review, referring someone — and lets them spend those points as a discount at checkout.

Points are a ledger. Every movement writes a row recording the type, the number of points, the balance before and after, where it came from and when it expires. A per-customer balance row is kept alongside as a running total, so a cart does not have to sum the whole ledger to know what a customer has.

Tiers sit on top: a tier is a points threshold with a multiplier, so a customer who has earned more earns faster. Moving between tiers fires its own events.

It is for stores running a loyalty programme.

Availability​

ItemValue
Module keyrewards_points
TierPremium
Entitlement keyrewards_points
Admin tabrewards-points
Enabled optionaiowc_module_enabled_rewards_points (off until turned on)
REST namespaceaiowc/v1

Enabling the module creates the four tables below and schedules the three jobs.

registerHooks() performs no licence check of its own; the module registry applies the entitlement gate centrally before calling it. It also registers the module's email automation triggers, so points events can drive the Email Automation module's sequences.

Settings​

This module declares no DEFAULTS constant. Its settings are read and written through GET/PUT /rewards/settings rather than being declared in the module class, so the admin screen is the place they are defined.

Earning​

An earning rule decides what a customer gets:

FieldMeaning
rule_typeWhat the rule rewards — a purchase, a signup, a review, a referral.
points_per_currencyPoints awarded per unit of order value, to four decimal places.
bonus_pointsA flat award, for rules that are not proportional to spend.
multiplierApplied on top of the base award.
target_type, target_idsNarrows the rule to particular products or categories.
min_order_valueA floor below which the rule does not fire.
valid_from, valid_untilThe window the rule is live in.
priority, is_activeOrdering, and whether the rule runs.

Awards are driven by real events: woocommerce_order_status_completed for a purchase, user_register for a signup, and comment_post plus wp_set_comment_status for a review — so review points are awarded on the moderated status, not merely on submission.

Points are taken back when an order stops being valid: the module hooks woocommerce_order_status_cancelled, _failed and woocommerce_order_refunded, and fires aiowc_rp_order_points_reversed when it does.

Tiers​

FieldMeaning
tier_id, nameThe tier's key and its display name.
min_points, max_pointsThe band of lifetime points it covers.
multiplierHow much faster this tier earns.
benefitsWhat the tier gives, as text.
color, iconHow the tier is presented.

Crossing a boundary fires aiowc_rp_tier_upgraded or aiowc_rp_tier_downgraded — downgrades included, so a tier is not permanent unless the store's thresholds make it so.

Redeeming​

A signed-in customer applies points at the cart and the module converts them to a discount on woocommerce_cart_calculate_fees. /public/rewards/max-redeemable says how many points may be spent on the current cart, so the control can cap itself rather than failing after the fact.

Expiry​

Points carry an expires_at. A daily job expires those past their date and a weekly job recalculates balances, which is what keeps the per-customer total honest against the ledger. Customers are warned first — the balance row carries expiring_soon and next_expiry_date, and a reminder job emails them.

Admin screen​

The Rewards & Points tab shows an overview, the customer list with balances, top earners and the distribution across tiers; manages earning rules and tiers; adjusts one customer's points with an audit trail; shows recent activity and a customer's own transactions; and carries a diagnostics endpoint for checking the module's configuration on a given store.

REST API endpoints​

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

Administrator routes — manage_woocommerce​

MethodPathPurpose
GET/rewards/overviewProgramme totals.
GET/rewards/customersCustomers and their balances.
GET/rewards/customers/{id}One customer.
GET/rewards/customers/{id}/transactionsThat customer's ledger.
POST/rewards/customers/{id}/adjustAdd or remove points (points).
GET/rewards/top-earnersThe highest balances.
GET/rewards/activityRecent movements across all customers.
GET / POST/rewards/earning-rulesList and create earning rules.
GET / PATCH / PUT / POST / DELETE/rewards/earning-rules/{id}Manage one rule.
GET / POST/rewards/tiersList and create tiers.
GET / PATCH / PUT / POST / DELETE/rewards/tiers/{id}Manage one tier.
GET/rewards/tiers/distributionHow customers are spread across tiers.
GET/rewards/diagnosticsThe module's own health detail.
GET / PATCH / PUT / POST/rewards/settingsRead and write the settings.

Customer routes​

MethodPathPurposePermission
GET/public/rewards/balanceThe caller's balance.Signed-in customer
GET/public/rewards/transactionsThe caller's ledger.Signed-in customer
GET/public/rewards/tierThe caller's tier.Signed-in customer
GET/public/rewards/expiringPoints about to lapse.Signed-in customer
GET/public/rewards/max-redeemableThe most that may be spent on this cart.Signed-in customer
POST/public/rewards/applySpend points on the cart (points).Signed-in customer
DELETE/public/rewards/removeTake applied points off the cart.Signed-in customer
GET/public/rewards/appliedWhat is applied to this cart.Signed-in customer
GET/public/rewards/calculateWhat an order would earn — usable signed out.Public, rate-limited

Every route that touches a balance resolves the customer from the session, so one customer's routes can never describe another's. /calculate is the only exception and reads nothing personal — it answers "what would this earn", which is what lets the product page advertise points to a visitor who has not signed in.

WooCommerce integration​

AreaHooks
Earningwoocommerce_order_status_completed, _processing, user_register, comment_post, wp_set_comment_status
Reversalwoocommerce_order_status_cancelled, _failed, woocommerce_order_refunded
Cartwoocommerce_cart_calculate_fees, _before_cart_totals, _cart_totals_before_order_total, _cart_emptied
Checkoutwoocommerce_checkout_order_processed
Displaywoocommerce_single_product_summary, _after_shop_loop_item_title, woocommerce_thankyou
Accountwoocommerce_account_menu_items, woocommerce_account_dashboard
Order displaywoocommerce_order_details_after_order_table, woocommerce_email_after_order_table
AJAXwp_ajax_aiowc_rp_apply_points, wp_ajax_aiowc_rp_remove_points

The AJAX handlers have no nopriv counterpart, which matches the module's design: points belong to an account, so a signed-out visitor has none to apply.

Database schema​

TableHolds
{prefix}aiowc_points_ledgerEvery movement: customer, type, points, balance before and after, source and source id, description, expiry, who made it.
{prefix}aiowc_points_earning_rulesThe rules: type, name, points per currency, targeting, multiplier, minimum order value, bonus points, validity window.
{prefix}aiowc_points_user_balanceOne row per customer: totals earned, redeemed and expired, current balance, points expiring soon and when, their tier, last activity.
{prefix}aiowc_points_tiersThe tiers: key, name, points band, multiplier, benefits, colour and icon.

The balance row is a running total kept alongside the ledger, not the source of truth. The weekly recalculation job exists to bring it back in line with the ledger if the two ever diverge.

Background jobs​

HookIntervalWork
aiowc_rp_expire_pointsdailyExpires points past their date and writes the ledger rows for it.
aiowc_rp_expiration_reminderdailyEmails customers whose points are about to lapse.
aiowc_rp_balance_recalcweeklyRebuilds each balance row from the ledger.

Each job fires its own completion event — aiowc_rp_expiration_job_completed, _reminder_job_completed, _recalc_job_completed — so a store can monitor that they actually ran.

Action hooks for integrators​

Points events: aiowc_rp_points_added, _subtracted, _redeemed, _refunded, _expiring, _expired, _balance_adjusted, _applied_to_cart, _removed_from_cart.

Award events: aiowc_rp_order_points_awarded, _order_points_reversed, _signup_bonus_awarded, _review_bonus_awarded, _referral_bonus_awarded.

Tier events: aiowc_rp_tier_upgraded, aiowc_rp_tier_downgraded.

Also aiowc_rp_earning_rule_created, aiowc_rp_settings_updated, the three job-completion events above, and aiowc_ea_fire_trigger for email automation.

Entitlement limits​

rewards_points is an on/off grant with no cap on the number of rules, tiers, customers or ledger rows. The point values and thresholds are store settings.

Health check​

The module reports a warning when its tables are missing or WooCommerce is inactive, and otherwise reports that it is functioning normally. The /rewards/diagnostics route gives more detail than the health check alone.

Known gaps​

  • The per-customer balance is a cached total reconciled weekly. Between reconciliations it is what the cart and the customer see, so a balance that drifts stays wrong for up to a week unless the recalculation is triggered sooner. There is no admin control to run it on demand.
  • A referral bonus event is fired but the module has no referral mechanism of its own — aiowc_rp_referral_bonus_awarded exists for something else to call, so referral points depend on another module or on custom code supplying the referral.
  • Settings are not declared as defaults on the module, so there is no single place in the code stating what they are and what they default to.
  • Tier assignment is stored on the balance row, so it is refreshed on the same cadence as the balance rather than the instant a threshold is crossed.
  • Points are a discount at the cart; there is no way to spend them on a specific product or to convert them into store credit.