AstroBaaS

Pricing & promotions

Lens Coating Upsell Engine (Optics)

Paid pluginsize Mplanned, not built

Indicative price, not an offer: €24/mo; auto-recommend coatings based on RX prescription, material

Generated from docs/plan/paid/lens-coating-upsell-engine/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

A paid module for optical retailers that recommends lens coatings based on customer RX (prescription) and lens material, increasing AOV 20–30%. The system stores a coating database (anti-glare, blue-light, polarized, etc.), calculates coating compatibility with material (glass vs polycarbonate), and inserts upsell prompts in the checkout flow with instant margin recovery.

The problem

An optics merchant cannot upsell coatings without knowing the customer’s RX; they currently ask ‘do you want AR coating?’ after purchase, losing 70% of upsells. With RX data in checkout (collected earlier in the flow), they can show ‘based on your RX, anti-glare is recommended for €15 extra’ and recover margin at point of decision.

What it does

  • Store optical database: coating types (anti-glare, blue-light, polarized, etc.), compatibility rules (glass/polycarbonate/trivex), cost per type, margin %
  • Collect RX in checkout: spherical (e.g., -2.50), cylindrical (-0.75), axis (175), add (1.00), PD (distance, near)
  • Recommend coatings at checkout: if RX < -3.0 (high myope) → recommend anti-glare; if RX > 2.0 (hyperope) + computer work → recommend blue-light
  • Display upsell in cart summary: ‘Add anti-glare (€15)’ as checkbox, recalculate order total dynamically
  • Store RX and selected coatings on order line item (order.items[].rx, order.items[].coatings[])
  • Admin manages coating database: add/remove coating types, set costs, define material compatibility
  • Analytics: show conversion rate (% of RX prescriptions who accepted coating upsell) and margin lift per coating type
  • Storefront SDK exposes coating recommendation logic (so headless frontends can call it directly)

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • Actual RX validation (optical professional requirements vary by country; we store what merchant inputs, not validate)
  • 3D lens visualization (storefront owns this; we provide RX + material data only)
  • Insurance billing or reimbursement (merchant handles with insurer; we track coatings for records only)

Data model

Add optical_coatings table: { id, shop_id, coating_name, description, cost_minor_units, margin_percent, material_compatibility (JSON: {glass: true, polycarbonate: true, trivex: false}) }. Add order.items[].optical_rx (JSON: {sph, cyl, axis, add, pd}) and order.items[].coatings[] (array of applied coating IDs). New table, no migration risk.

API

  • GET /products/:id/coatings/recommend?rx={sph,cyl,axis,add,pd} — returns recommended coatings for RX
  • POST /checkout/coatings/apply — add coating to line item (recalculates price)
  • GET /admin/optical/coatings — list all coatings, costs, compatibility
  • PUT /admin/optical/coatings/:id — edit coating (cost, compatibility rules)

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Add ‘Optical Setup’ section in Commerce > Product Categories or Settings. Table: coating types, cost (€), material compatibility (checkboxes). Add ‘Recommendation Rules’ editor: if RX.sph < -3.0 → recommend ‘anti-glare’, else if RX.sph > 2.0 → recommend ‘blue-light’. Show analytics: ‘Anti-glare accepted 45% of the time, avg add-on €15’.

The seam — why this is paid

Paid module owns the optical upsell algorithm, coating database, and material compatibility rules. This is specific to optical retail and requires domain expertise (optical professionals curate rules). Core owns the order line item structure and price calculation; module builds on it.

Support commitment: optical upsell algorithm, lens-material database updates

Dependencies

  • Product system (line items must be editable at checkout)
  • Checkout flow (to inject RX collection and coating recommendation UI)
  • Order data model (to store RX and applied coatings)

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • For RX = {sph: -3.5}, the recommendation engine suggests anti-glare coating
  • Adding anti-glare coating to cart increases order.subtotal by the coating cost (€15)
  • Coating compatibility: if material = ‘glass’ but coating compatibility = {glass: false}, coating is not recommended
  • Order line item stores optical_rx as {sph: -2.50, cyl: -0.75, axis: 175, add: 1.00, pd: 63.5}
  • Analytics dashboard shows ‘Anti-glare: 45% acceptance rate, €12 avg add-on, 30% margin’
  • Admin can add new coating type ‘Photochromic’ with cost €40 and material compatibility rules

Risks

If RX data is stored as strings instead of numbers, calculation (sph < -3.0) fails. If coating cost is added without recalculating tax, checkout total is wrong. If recommendation rules are hard-coded instead of configurable, merchants cannot adapt to their market (all shops would get the same rules).

Commercial context

Suggested price€24/mo; auto-recommend coatings based on RX prescription, material
Rival anchorCustom logic: €1500+; no Shopify app

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.