Skip to main content

Opportunities

Levers for growth

Sovarium finds opportunities for growth in your data, with the estimated impact of each. Open one of this week’s.Here are this week’s opportunities.

Opportunities

Levers for growth that Sovarium finds in your data, updated once a week.

Recover orders lost to declined cards: 34 web orders worth £4,610 went unpaid this month, and nothing reminded the buyers

Estimated impact

About £1.6K a month in orders now lost at payment

How this was calculated
Arithmetic
38 web orders a month with a failed card × (43% − 11%) paid within a day ≈ 12 more paid orders. 12 × £135.60, the average unpaid web order = £1,627 a month.
Assumption
Web buyers answer an email the way app buyers answer the app’s reminder, and web cards keep failing at this month’s rate.

Actions to take

Email web buyers whose card fails a link back to their order within the hour. The app reminds users and failed app purchases have a 3.9x higher second payment attempt rate. Hold back one in ten at random, so the difference in paid orders shows what the email itself brought in.

Why this came up

52 orders in the last 30 days had their first card payment fail. Orders placed in Orion’s app get a reminder to finish paying, and 6 of those 14 were paid within a day, 43%. The website sends nothing, and 4 of its 38 were, 11%. The 34 web orders never paid were worth £4,610, £135.60 each on average. This complements the checkout accounts you are pursuing: those keep buyers after their first order, this saves the orders lost before they are paid.

Show queryHide query
WITH failed AS ( SELECT o.ord_id, o.src_sys_cd AS placed_on, o.ord_ccy_cd, o.amt_2, MIN(p.pmt_ts) AS first_try, MIN(p.pmt_ts) FILTER (WHERE p.pmt_stat_cd IN (2, 5)) AS paid_ts FROM marketplace.orn_ord_hdr o JOIN marketplace.pmt_txn p ON p.ord_id = o.ord_id LEFT JOIN marketplace.cust_mst c ON c.cust_id = o.cust_id WHERE o.dt_1 >= CURRENT_DATE - 30 AND o.src_sys_cd <> 'INTERNAL_TEST' AND NOT COALESCE(c.is_test_acct, false) GROUP BY o.ord_id, o.src_sys_cd, o.ord_ccy_cd, o.amt_2 HAVING MIN(p.pmt_ts) = MIN(p.pmt_ts) FILTER ( WHERE p.pmt_stat_cd = 3 AND p.pmt_mthd_cd = 'CARD' ))SELECT f.placed_on, COUNT(*) AS card_failed, COUNT(*) FILTER ( WHERE f.paid_ts < f.first_try + INTERVAL '1 day' ) AS paid_within_a_day, COUNT(*) FILTER (WHERE f.paid_ts IS NULL) AS never_paid, ROUND(SUM(f.amt_2 * fx.to_gbp) FILTER ( WHERE f.paid_ts IS NULL ), 2) AS never_paid_gbpFROM failed fCROSS JOIN LATERAL ( SELECT COALESCE(MAX(x.rate) FILTER (WHERE x.ccy_from = f.ord_ccy_cd), 1) / MAX(x.rate) FILTER (WHERE x.ccy_from = 'GBP') AS to_gbp FROM lgcy.fx_daily_rate x WHERE x.fx_dt = (SELECT MAX(fx_dt) FROM lgcy.fx_daily_rate WHERE fx_dt <= f.first_try::date)) fxGROUP BY 1ORDER BY 2 DESC

The marked lines come from the Context Layer, not the schema:

  • Status 3 is a failed payment; 2 and 5 are captured.
  • Test orders are left out, including those from test accounts.
  • An unpaid order has no captured amount, so it is valued at its checkout total after discounts.
  • Rates are quoted to dollars on business days only, so each order takes the latest rate on or before its day.

Orders whose first card payment failed

Orders placed in the last 30 days, by where they were placed.

Placed onCard failedPaid within a dayNever paidNever paid, value
WEB38434£4,610
APP1468£1,090

2 rows

Cut damage refunds by having the warehouse pack fragile Home & Kitchen items: they were £1,480 of the £2,100 refunded for damage

Estimated impact

About £760 a month less refunded for damage

How this was calculated
Arithmetic
£1,480 of Home & Kitchen damage refunds a month × (1 − 2.1% ÷ 4.3%) = £757 a month.
Assumption
Items the warehouse packs arrive damaged at its 2.1% rate instead of the sellers’ 4.3%, and the mix of items stays the same.

Actions to take

Offer the 12 Home & Kitchen sellers who ship to the EU warehouse fulfilment for their glass and ceramics, so Orion’s warehouse packs them. Start with the 4 sellers behind 7 of the 11 damage refunds, and compare their damage refunds after four weeks.

Why this came up

Refunds for damage in transit came to £2,100 over the last 30 days, the largest refund reason, and returns logged as damaged doubled last week, from 6 to 12. Home & Kitchen items were 11 of the 16 damage refunds, £1,480 of the £2,100, and 9 of those 11 were shipped to EU addresses. Home & Kitchen parcels that Orion’s warehouse packs arrive damaged 2.1% of the time, against 4.3% for the ones sellers pack themselves. Carriers can’t change before January, so this works on the packing.

Show queryHide query
SELECT COALESCE(top.cat_nm, cat.cat_nm) AS category, COUNT(*) AS refunds, ROUND(SUM(r.rfnd_amt * fx.rate), 2) AS refunded_gbpFROM marketplace.rfnd rJOIN marketplace.orn_ord_hdr o ON o.ord_id = r.ord_idJOIN LATERAL ( SELECT l.prod_id FROM marketplace.ord_ln l WHERE l.ord_id = r.ord_id AND NOT l.is_rfnd_ln ORDER BY l.ln_amt DESC LIMIT 1) item ON trueJOIN marketplace.prod_mst p ON p.prod_id = item.prod_idJOIN marketplace.categories cat ON cat.cat_id = p.cat_idLEFT JOIN marketplace.categories top ON top.cat_id = cat.parent_cat_idJOIN lgcy.fx_daily_rate fx ON fx.fx_dt = r.proc_ts::date AND fx.ccy_from = o.ord_ccy_cdWHERE r.rfnd_rsn_cd = 1 AND r.proc_ts >= CURRENT_DATE - 30GROUP BY 1ORDER BY refunded_gbp DESC

The marked lines come from the Context Layer, not the schema:

  • Reason 1 is damaged in transit.
  • A refund counts from when it was paid back, not when it was asked for.
  • Each refund takes its category from the order’s main item, never from a refund line.
  • Subcategories roll up to their top-level category.
  • Refunds are in the order’s currency, converted at the day’s rate.

Refunds for damage in transit, by category

Refunded value for items damaged in transit over the last 30 days.

Bar chart. Refunds for damage in transit in the last 30 days, by category: Home & Kitchen £1,480, Electronics £310, Fashion £180, Toys & Games £90, Beauty £40.

Restock 14 best sellers that have run out in Orion’s warehouse: they sold £71 a day between them, and none has stock on the way

Estimated impact

About £2.1K in sales for every month they stay out of stock

How this was calculated
Arithmetic
£71 a day, what the 14 sold together before running out × 30 days = £2,130 a month.
Assumption
Back in stock, each listing sells at its pace over the eight weeks before its last sale.

Actions to take

Ask the three sellers behind 8 of the listings to send stock in this week, then the rest. Have the warehouse tell a seller whenever one of their listings is down to two weeks of sales, counting what is on the way.

Why this came up

14 listings that Orion’s warehouse stocks sold in at least 7 of the 8 weeks before their last sale, and their latest counts show none on hand and none on the way. Together they sold £71 a day over those eight weeks. 9 of them have now gone more than a week without a sale, and 8 of the 14 belong to three sellers.

Show queryHide query
WITH latest AS ( SELECT DISTINCT ON (listing_id, whse_id) listing_id, qty_on_hand, qty_incoming FROM ops.inv_snap ORDER BY listing_id, whse_id, snap_dt DESC),stock AS ( SELECT listing_id, SUM(qty_on_hand + qty_incoming) AS units FROM latest GROUP BY 1),sold AS ( SELECT l.lstg_id, o.dt_2, l.ln_amt * fx.to_gbp AS line_gbp, MAX(o.dt_2) OVER (PARTITION BY l.lstg_id) AS last_sale FROM marketplace.ord_ln l JOIN marketplace.orn_ord_hdr o ON o.ord_id = l.ord_id CROSS JOIN LATERAL ( SELECT COALESCE(MAX(x.rate) FILTER (WHERE x.ccy_from = o.ord_ccy_cd), 1) / MAX(x.rate) FILTER (WHERE x.ccy_from = 'GBP') AS to_gbp FROM lgcy.fx_daily_rate x WHERE x.fx_dt = (SELECT MAX(fx_dt) FROM lgcy.fx_daily_rate WHERE fx_dt <= o.dt_2::date) ) fx WHERE o.dt_2 IS NOT NULL AND NOT l.is_rfnd_ln AND o.ord_stat_cd <> 7 AND NOT EXISTS (SELECT 1 FROM marketplace.ord_cxl x WHERE x.ord_id = o.ord_id) AND o.src_sys_cd <> 'INTERNAL_TEST'),pace AS ( SELECT lstg_id, MAX(last_sale) AS last_sale, COUNT(DISTINCT date_trunc('week', dt_2)) AS weeks_sold, SUM(line_gbp) / 56 AS gbp_a_day FROM sold WHERE dt_2 > last_sale - INTERVAL '56 days' GROUP BY 1)SELECT CASE WHEN CURRENT_DATE - p.last_sale::date < 7 THEN 'Under a week' WHEN CURRENT_DATE - p.last_sale::date < 14 THEN '1–2 weeks' WHEN CURRENT_DATE - p.last_sale::date < 21 THEN '2–3 weeks' ELSE '3+ weeks' END AS since_last_sale, COUNT(*) AS listings, ROUND(SUM(p.gbp_a_day), 2) AS gbp_a_dayFROM pace pJOIN stock s ON s.listing_id = p.lstg_idJOIN marketplace.listings l ON l.lstg_id = p.lstg_idWHERE s.units = 0 AND p.weeks_sold >= 7 AND l.lstg_stat_cd = 2 AND NOT l.del_flgGROUP BY 1ORDER BY MAX(p.last_sale) DESC

The marked lines come from the Context Layer, not the schema:

  • The warehouse counts only the stock it holds, at irregular times, so each listing is read at its latest count in each warehouse, never summed across counts.
  • A sale counts once its payment is captured. Refund lines, test orders and cancelled orders are left out, including cancellations the order’s status never shows.
  • Status 2 is a live listing, and deleted listings are left out.
  • Each sale is converted to pounds at the latest rate on or before its day.

Best sellers with no stock, by time since their last sale

Listings in Orion’s warehouse that sold in at least 7 of the 8 weeks before their last sale, with none on hand and none on the way.

Bar chart. 14 best sellers with no stock, by time since their last sale: under a week 5, 1 to 2 weeks 4, 2 to 3 weeks 3, 3 weeks or more 2.

Example data.

Feedback drives action

Tell the agent why you are or aren't pursuing an idea and the feedback is incorporated into the next run.

  1. Week of 21 SepPursuing

    Offer guests an account at checkout

    “Adding a one-click account option to the order confirmation page this sprint.”

    Set by Priya Nair, 6d ago

    A week later:

    Week of 28 Sep

    Recover declined card payments

    This complements the checkout accounts you are pursuing: those keep buyers after their first order, this saves the orders lost before they are paid.

  2. Week of 21 SepDismissed

    Reward repeat buyers with points

    “We ran a points scheme in 2025 and it cost more than it brought in.”

    Set by Maya Okafor, 1w ago

    A week later:

    Week of 28 Sep

    Nothing this week rewards repeat buyers.

    A dismissed idea stays out, close variants too, until it expires. This one expires on 22 Mar 2027.

  3. Week of 21 SepNot possible

    Move EU parcels to another carrier

    “We can’t change carriers before January. The contract runs to the end of the year.”

    Set by Olivia Mason, 1w ago

    A week later:

    Week of 28 Sep

    Pack fragile items for the EU

    Carriers can’t change before January, so this works on the packing.

The self-learning loop

  1. Monday, 5am

    Exploratory data analysis begins

  2. Brainstorming

    New ideas and opportunities are compared against previous ideas and feedback.

  3. Deep Research

    The top ideas are fully explored and validated

  4. Presentation

    The ideas that bear fruit are presented in your Opportunities dashboard.

  5. Feedback

    You decide whether to mark as Pursue, Not possible or Dismiss with the reason why.

  6. Memory

    Your feedback is logged as memory so that future ideas can be compared against it.

Start the loop on your own data.

Tell us about your warehouse and your team. Our data experts write your Context Layer, then every Monday Sovarium will bring you new opportunities for growth.