Skill

Promo Margin Guard

Compute the true contribution margin of a discount or promotion after COGS, shipping, payment fees, refunds and expected returns, identify which promo codes lost money, solve the breakeven discount depth for every product, and list the…

At a glance

Promo Margin Guard is an AI skill that you can use in Claude Code, Codex, or type.com.

Updated

See an example

Example output from a sample run. Company names and figures are sample data.

Promotion margin guard: Willow & Ash, 6 promo codes across 670 orders

Expected contribution margin is 3,287.78, only 4.9% of net revenue, after 26,443.75 of discount (28.4%). CLEARANCE50 and FLASH40 lost money, VIP30 is thin, and 1 of 13 SKUs must be excluded or capped for the next 25% sitewide sale.

PromoOrdersNet revBooked marginExpected marginMargin%
CLEARANCE50906,354.00-545.15-1,345.12-21.2%
FLASH4018016,250.40695.74-1,316.03-8.1%
VIP30706,910.401,152.78209.003.0%
SPRING2015015,935.204,370.541,836.9711.5%
(no code)608,287.003,334.741,878.2122.7%
WELCOME1512013,094.254,052.582,024.7515.5%
TOTAL67066,831.2513,061.233,287.784.9%

Expected margin subtracts the returns still to come: refunds, return handling, and the stock they will recover.

SKUProductReturn %GivenBreakevenHeadroom
WA-BOOT-CHLChelsea Boot45.0%29.2%22.0%-7.2%
WA-DRESS-MIDMidi Slip Dress45.0%27.9%25.8%-2.0%
WA-GIFT-SETCabin Gift Set8.0%28.2%28.3%0.1%
WA-KNIT-MERMerino Crew Knit30.0%26.3%31.5%5.2%
WA-JEAN-STRStraight Leg Selvedge Jean38.0%31.5%36.3%4.8%

…plus 8 more SKUs with deeper headroom in the full report.

Next actions

  • Cap WA-BOOT-CHL at 22.0% in the next 25% sitewide sale; at 25% each unit contributes -3.08.
  • Watch WA-DRESS-MID and WA-GIFT-SET: breakevens of 25.8% and 28.3% are barely above the planned 25%, so any stacked code or free shipping tips them negative.
  • Rethink CLEARANCE50 and FLASH40: they run -14.95 and -7.31 per order at 50.0% and 40.0% average discounts. FLASH40's booked margin was 695.74, but its returns still to come cost 2,011.77 net of recovered stock.

Inputs: promo orders, order lines and product costs; fulfillment 2.85 per order, return handling 8.50 per returned unit, 75% of unit cost recovered, payment fee 2.9% + 0.30 per order. No finance/revenue_definitions.json was found, so the skill's own defaults apply. With that file present, the skill converts CAD orders at the order date's FX rate and removes excluded test, cancelled, voided and internal orders.

Produced by running bash examples/run.sh on the sample data bundled with this skill.

How to use Promo Margin Guard

  1. type.com: Choose Use Skill to add Promo Margin Guard to your type.com workspace.
  2. Claude Code: Download the skill and extract it into ~/.claude/skills/promo-margin-guard/ (or .claude/skills/promo-margin-guard/ in a project). Then ask Claude to use Promo Margin Guard.
  3. Codex: Download the skill and extract it into ~/.agents/skills/promo-margin-guard/ (or .agents/skills/promo-margin-guard/ in a repository). Then ask Codex to use Promo Margin Guard.

AI agents can read this page as Markdown or fetch the raw SKILL.md.

Frequently asked questions

What is Promo Margin Guard?

Promo Margin Guard is an AI skill that you can use in Claude Code, Codex, or type.com.

What does Promo Margin Guard do?

Compute the true contribution margin of a discount or promotion after COGS, shipping, payment fees, refunds and expected returns, identify which promo codes lost money, solve the breakeven discount depth for every product, and list the…

Can I use Promo Margin Guard in Claude Code or Codex?

Yes. Promo Margin Guard is a standard Agent Skills folder with a SKILL.md file. Download it and extract it into ~/.claude/skills/ for Claude Code or ~/.agents/skills/ for Codex.

Who created Promo Margin Guard?

The type.com team created Promo Margin Guard. The type.com team reviews every skill before it is published in the Skills Library.

  • Budget PacerProject month-end spend from a trailing run rate across campaigns and clients, flag over- and under-delivery beyond a tolerance, and recommend per-campaign daily budgets that reconcile exactly to each client's committed total.
  • BFCM Cohort QualityFind out if last Black Friday's new customers were worth it: contribution, repeats and payback vs October and January buyers, by discount, source and product.
  • Holiday Support MacrosPrepare your support team for BFCM: forecast holiday tickets and staffing, find policy gaps and stale macros, and generate holiday macros built only from your written policies.
  • Holiday Shipping Cutoff CheckerFind the last day customers can order on each shipping service and still get it by the holiday, check every delivery promise against it, and plan the switch to expedited and e-gift cards.
  • BFCM Live PulseTurn hourly sales and ad spend into a BFCM status update with sales pacing, budget guardrails, checkout alerts, code-use anomalies and stock risk.
  • BFCM Offer & Discount Config QACheck your Shopify BFCM discounts against the offer plan before launch: stacking, sale windows, who gets each discount, code limits and free shipping, with test carts and a dated fix list.

AI for ecommerce: a practical guide

Browse the technical files
---
name: promo-margin-guard
description: Compute the true contribution margin of a discount or promotion after COGS, shipping, payment fees, refunds and expected returns, identify which promo codes lost money, solve the breakeven discount depth for every product, and list the SKUs to exclude or cap in the next sitewide sale.
---

# Promo Margin Guard

A promotion's revenue is easy to see and its cost is not. This prices the
whole promotion: what was given away, what the goods cost, what shipping and
fees ate, and what the returns that have not landed yet will take back. Then
it works backwards to the deepest discount each product can actually carry.

## Before you run

This skill ships scripts and sample data alongside this SKILL.md. Before running any command:

1. **Get the files.** Make sure the skill's other files (`scripts/`, `examples/` and anything else listed with this skill) are in your working folder at the same relative paths. Some environments load only SKILL.md; if yours did, fetch each file from this skill's published files and write it to the matching path. In Type, read them with the skill-file tools. Anywhere else, the Type Skills Library API lists every file with its path, content and `sha256`: GET `https://api.type.com/api/public/library/skills` and take the entry with slug `promo-margin-guard`.
2. **Check the copies are exact.** Compare each file's size in bytes, not characters (and its hash, where your tools report one), with the published version before running. A copy written out from the published file is fine once its byte size and hash match; never run a script you summarised or reconstructed from memory.
3. **Run from the skill's folder**, calling interpreters explicitly: `python3 scripts/…` and `bash examples/run.sh`.
4. **Try the sample first.** If the skill ships `examples/run.sh` and `examples/expected_output.txt`, run `bash examples/run.sh`; its output should match the expected file exactly. If it doesn't, stop and report the first differing line rather than running on real data.

## When to use this

- After any sale, code, or campaign, to settle whether it made money.
- **Before** a sitewide sale, to decide the depth and the exclusion list.
- When a founder or finance lead asks "should we run 20% or 30% off?"
- When a specific code is suspected of being abused or stacked.
- Quarterly discount hygiene: which evergreen codes (welcome, winback, VIP)
  are quietly unprofitable.

## Gathering the input

Three local files; the script never touches the network.

**1. Promotion orders** (`--orders`), one row per order.
- **Shopify**: Orders export filtered to the promotion window, or the
  Discounts report drilled into orders. Keep `Discount Code`, discount amount,
  subtotal *before* discount, shipping charged, and refunded amount.
- Include a control group if you can: orders in the same window with **no**
  code. Leave `promo_code` empty and they bucket as `(no code)`, giving you a
  baseline margin rate to compare the promo rates against.
- `gross_revenue` must be **before** the discount. If the export only has
  post-discount revenue, add the discount back before running, or every
  breakeven number will be wrong.

**2. Order line items** (`--lines`), one row per order line. Needed to push
COGS, shipping, fees, and refunds down to SKU level. Shopify's line-item
order export or a warehouse `order_lines` table both work.

**3. Product costs** (`--products`): SKU, landed unit cost, list price, and —
important — `return_rate_pct` per SKU. Costs usually come from an ERP, 3PL,
or the purchasing spreadsheet, not the storefront. Return rates come from the
returns platform (Loop, Returnly, AfterShip) or from a returns report over the
last 6–12 months. Typical DTC ranges to sanity check against: 4–10% for
accessories and home goods, 12–20% for knitwear and tops, 25–45% for footwear,
denim, and fitted dresses. If you only have a blended rate, pass
`--return-rate-pct` and say so in the writeup.

## Running it

```bash
python3 scripts/promo_margin.py \
  --orders examples/promo_orders.csv \
  --lines examples/promo_lines.csv \
  --products examples/products.csv \
  --fulfillment-cost 2.85 \
  --return-shipping-cost 8.50 \
  --restock-recovery-pct 75 \
  --planned-discount-pct 25
```

- `--planned-discount-pct` is the depth of the sale you are about to run; the
  exclusion list is built against it.
- `--payment-fee-pct` / `--payment-fee-fixed` default to 2.9% + 0.30. A
  `payment_fee` column in the orders file overrides them.
- `--fulfillment-cost` is pick, pack, and box per order.
- `--return-shipping-cost` is what one returned unit costs to get back and
  process; `--restock-recovery-pct` is how much of its unit cost you recover
  by reselling it. Footwear and apparel rarely recover 100%.
- `--min-unit-margin` raises the bar for the breakeven solve above zero, for
  example `--min-unit-margin 5.00` to require five dollars of contribution.
- `--json` for machine-readable output. Each promotion carries a
  `bookedToExpectedBridge` with the same cent-exact steps as the text bridge;
  use it rather than rounding the raw components yourself.

There is no date argument and no clock read: every figure comes from the data
and the stated assumptions. Bad input exits 2 naming the file, row, and column.

## Reading and presenting the output

- **Promotion P&L**, one row per code, sorted worst margin first, with a
  TOTAL row. `returns` combines refunds already taken, the revenue expected to
  come back, and return handling.
- **Booked versus expected.** Booked margin counts only what has already
  happened: refunds already processed, plus the return handling and the
  recovered stock on those same returned units. Expected margin is booked
  minus the full effect of the returns still to come: the revenue they will
  refund, minus their handling, plus the stock they will recover. The
  **booked to expected bridge** prints those three steps per promo and they
  add up to the cent. For a promotion that ran in the last few weeks, booked
  margin is flattering and expected margin is the honest number — lead with
  expected and use the bridge to reconcile to what finance has seen so far.
- **Promotions that lost money**, with per-order loss and the returns cost
  that pushed them under. `[THIN]` entries cleared costs but on under 10%
  contribution margin.
- **Breakeven discount depth by product**, sorted shallowest first. `given` is
  what the SKU actually received; `headroom` is breakeven minus given. A
  negative headroom means that SKU has already been discounted past its
  breakeven.
- **Exclude from the next sale**, split into hard caps and thin-headroom
  warnings.

When reporting to a human:

1. Open with the total: full-price value, discount given away, and expected
   contribution margin as a percentage of net revenue. Compare it with the
   `(no code)` baseline row if one exists.
2. Name the codes that lost money and the per-order loss. "FLASH40 lost $7.31
   on every order it touched" lands; "-8.1% margin" does not.
3. Give the exclusion list as a concrete instruction for the next sale: these
   SKUs out, these capped at this depth, everything else fine at the planned
   depth.
4. Separate the *depth* problem from the *mix* problem. If the codes are fine
   but the discounted mix skewed to low-margin, high-return SKUs, the fix is
   exclusions, not a shallower sitewide depth.
5. Caveat acquisition: a money-losing welcome code can still be correct if the
   customers it buys repeat. That question belongs to a cohort LTV analysis,
   not to this one — say so rather than calling the code a mistake outright.

## Limits

- **Contribution margin only.** No ad spend, no overheads, no payroll, no
  warehousing rent, no platform or app fees. A promo that "made money" here
  covered its variable costs, not the business.
- **No acquisition value.** A first-order discount that loses money on order
  one may be the cheapest customer acquisition the brand has. This skill has
  no view of repeat purchasing; pair it with cohort analysis before killing a
  welcome or winback code.
- **No incrementality.** It cannot tell you whether a discounted order would
  have happened anyway at full price. The `(no code)` bucket is a comparison,
  not a control group. Every conclusion is "what this promotion earned", never
  "what this promotion caused".
- **Expected returns are a rate applied to revenue, not a returns forecast.**
  There is no per-order return prediction, no seasonality, and no allowance for
  the fact that deeply discounted goods are often returned *more*. If anything,
  return-driven losses on deep promos are understated here.
- **Line-level allocation is pro-rata by gross line revenue.** Shipping,
  fees, and refunds are spread across lines by their share of the order, which
  is right on average and wrong for any single mixed basket — a heavy item in
  a light basket is under-charged for shipping.
- **Payment fees are assumed non-refundable**, which matches most processors
  but not all, and they are charged on the amount captured.
- **Breakeven depth is per unit at list price**, using that SKU's observed
  shipping economics from this data. It does not model bundles, BOGO
  mechanics, gift-with-purchase, tiered thresholds, or stacked codes. For a
  BOGO, express it as its equivalent percentage depth before running.
- Orders whose line items do not sum to the order total within 1% are flagged
  under DATA QUALITY; their per-SKU figures are distorted.