Skip to content

Loyalty & gamification

Status

Tables live, endpoints stubbed, UI pending. fruitplug-api created all the tables on activation (2026-04-24); the PWA surfacing comes in Phase 2.

The plan

All of this is owned by fruitplug-api and stored in the WordPress MySQL DB. See Data model for schema details.

Plug Points

1 point per £1 spent. 10 points = £1 off.

flowchart LR
  A[woocommerce_order_status_completed] --> B[PointsLedger::award_for_order]
  B --> C[(wp_fruitplug_points_ledger<br/>append-only)]
  B --> D{referral code<br/>in order meta?}
  D -- yes --> E[credit referrer +1000<br/>credit referee +1000]

The ledger is append-only. Balance is derived by SUM(delta) WHERE user_id = ?. To reverse an earn, append a negative-delta row — never mutate history.

Streaks

Daily cron: for each user with a completed order in the current ISO week, bump current_length by 1. If last_week_iso wasn't the previous week, reset to 0.

Tier Weeks in a row
Bronze 1–3
Silver 4–7
Gold 8–15
Plug VIP 16+

See wp-plugin/fruitplug-api/includes/Cron/StreakEvaluator.php.

Fruit Passport

Every unique product a user has ordered earns a stamp. Complete rows for rewards (e.g. try all 5 dragon fruits → free upgrade next box).

Stamps live in wp_fruitplug_passport with times_ordered incremented on each re-order.

Referrals

  • Customer taps SharePOST /wp-json/fruitplug/v1/referrals/code returns their unique code (lazily created).
  • Referee enters code at checkout → the PWA stores it as order meta (_fruitplug_referral_code).
  • On referee's first completed order, the PointsLedger hook credits both parties 1,000 points (tune later).

Spin-to-win (planned)

Triggered on:

  • First-ever visit (conversion hook)
  • After 3rd, 5th, 10th orders (retention hooks)

Prizes are entries in the points ledger (reason=spin_reward).

Live REST endpoints

GET /wp-json/fruitplug/v1/loyalty/me (requires login) returns the current user's points balance, streak tier + length, and passport stamp count — combined from the three relevant tables.

Example response:

{
  "user_id": 42,
  "points": 2430,
  "streak": { "current_length": 6, "best_length": 11, "tier": "silver" },
  "passport_stamps": 14
}

PWA surfacing (Phase 2)

  • /account — hero showing points + tier + streak bar
  • /account/passport — visual grid of all 26 fruits with stamps on tried ones
  • /account/referrals — share CTA with code, list of credited referrals
  • Cart line: "You'll earn X Plug Points on this order"