TL;DR: The revenue recognition 5 steps from ASC 606 tell Shopify brands when a sale becomes revenue. Identify the contract, list the performance obligations, set the transaction price, allocate it across SKUs, then recognize revenue when each item ships. Pre-orders, subscriptions, bundles, and gift cards each break the simple "order = revenue" assumption. This guide walks through each one with journal entries.
This tutorial walks Shopify operators and their bookkeepers through the revenue recognition 5 steps using real DTC transactions: a pre-order drop, a Recharge subscription box, a bundle with a free gift, and a gift card sale. You will see when revenue hits the P&L and the journal entry behind each step. The examples mirror the patterns Ottit applies across the 100+ Shopify stores we close books for in 2026.
1What you'll need before you start
- Shopify admin access with Reports permission
- Order data from your subscription app (Recharge, Skio, or Bold)
- QuickBooks Online or Xero as your general ledger
- A revenue recognition tool — we use Bookkeep across the 100+ Shopify stores Ottit closes books for
- SKU-level standalone selling prices for each product in any bundle
- Fulfillment data from Shippo, ShipBob, or your 3PL (ship dates drive recognition)
2What is the revenue recognition 5-step model?
The revenue recognition 5-step model is the ASC 606 framework that tells a business when a sale becomes revenue on the income statement. It comes from FASB ASC 606 (Revenue from Contracts with Customers) and applies to every Shopify brand on accrual accounting. Cash in the bank is not the trigger. Delivery of the promised product is.
- Identify the contract with the customer
- Identify the performance obligations in the contract
- Determine the transaction price
- Allocate the transaction price to each performance obligation
- Recognize revenue when (or as) each obligation is satisfied
Steps 1, 3, and 5 are usually mechanical for DTC. Steps 2 and 4 are where brands get into trouble — especially with bundles, free-gift promos, and subscription tiers. We will spend extra time on those.
Quick comparison: cash basis vs. ASC 606 accrual for Shopify
The table below shows how the same Shopify transactions hit the books under each method. Most Shopify brands over $1M in revenue need the right column for clean financials and any future diligence.
| Transaction | Cash basis timing | ASC 606 accrual timing |
|---|---|---|
| Standard order shipped same day | Revenue at payment | Revenue at ship date |
| Pre-order paid today, ships in 6 weeks | Revenue at payment | Deferred until ship date |
| 12-month prepaid subscription | Revenue at payment | 1/12 recognized each ship |
| $100 gift card sold | Revenue at sale | Liability until redeemed |
| Bundle of 3 SKUs | One revenue line | Allocated across 3 SKUs |
| Customer-paid shipping | Revenue at payment | Revenue at ship date |
3Identify the contract (Step 1)
For Shopify DTC, the contract is the order itself. When a customer clicks Place Order, the Shopify checkout creates a written agreement to deliver products in exchange for payment. The order ID is your contract reference. No paperwork needed.
Pre-order example
A skincare brand runs a pre-order on a new SKU shipping in 6 weeks. The customer pays $60 today. The contract exists at checkout. But the obligation has not been satisfied yet. Cash comes in, but it sits as a liability.
Takeaway: a Shopify order ID is sufficient documentation for Step 1. The harder question is when delivery happens, not whether a contract exists.
4Identify the performance obligations (Step 2 — the one most brands get wrong)
A performance obligation is each distinct good or service promised in the order. The mistake we see across Shopify books is treating a bundle as one obligation when it's actually several. If the customer could buy each item separately and each provides standalone value, each item is its own performance obligation.
Bundle with a free gift example
A coffee brand sells a Starter Bundle for $80. It contains a 12oz bag of beans (sold standalone for $24), a ceramic mug (sold standalone for $30), and a "free" branded scoop (sold standalone for $12). Shopify shows one line: Bundle SKU $80. The general ledger has to see three obligations.
| Item | Standalone Price | Standalone Value? | Performance Obligation? |
|---|---|---|---|
| 12oz coffee bag | $24 | Yes | Yes |
| Ceramic mug | $30 | Yes | Yes |
| Branded scoop ('free') | $12 | Yes (sold alone) | Yes |
| Bundle SKU itself | $80 | Not separate | No — it's a wrapper |
Subscription box example
A Recharge subscriber pays $35/month for a snack box. Each monthly box is a separate performance obligation, satisfied when that box ships. A 12-month prepaid subscription is 12 obligations, not one. The annual charge sits in deferred revenue and bleeds out monthly.
Takeaway: every bundle SKU in Shopify needs a component map in the chart of accounts or in a tool like Bookkeep. Without it, Step 4 cannot be done correctly.
5Determine the transaction price (Step 3)
The transaction price is what the brand actually expects to keep. For Shopify, that means the order subtotal after discounts, plus shipping the customer paid, minus expected refunds and returns. Sales tax collected is not revenue — it is a pass-through liability.
- Start with the gross order amount in Shopify
- Subtract discount codes applied at checkout
- Subtract a refund/return reserve based on the brand's historical return rate
- Exclude sales tax collected (sits in a Sales Tax Payable liability)
- Treat customer-paid shipping as part of the transaction price (it is a service obligation, satisfied at delivery)
For most Shopify brands on accrual books, the return reserve is the trickiest piece. A typical apparel DTC brand running a 12% return rate accrues a returns reserve at close. Supplements and consumables often run under 2%.
Typical return rates by Shopify category
The numbers below are the ranges we typically see across the brands Ottit closes books for. They inform the returns reserve booked at month-end close.
| Category | Typical return rate | Notes |
|---|---|---|
| Apparel and footwear | 10–20% | Sizing drives most returns |
| Beauty and skincare | 3–6% | Sample-size returns common |
| Supplements | 1–3% | Often non-returnable |
| Food and beverage | <2% | Perishable, rarely returned |
| Home goods | 5–10% | Damage in transit drives returns |
| Electronics and accessories | 8–15% | High DOA component |
Calculating transaction price on a $120 order
Takeaway: the transaction price is not the Shopify order total. Pull discounts, tax, and a returns reserve out before moving to Step 4.
6How to allocate the transaction price across SKUs (Step 4 — the other one brands get wrong)
Once you know the transaction price and the performance obligations, you split the price across them based on standalone selling prices. Discounts get allocated proportionally to every SKU, not dumped on one item. This is the step where most Shopify books quietly fall out of GAAP.
Allocating the coffee Starter Bundle
The bundle sells for $80. Standalone prices add up to $24 (coffee) + $30 (mug) + $12 (scoop) = $66. The customer paid $80 for the bundle, so the allocation here is simpler — but the same proportional logic applies when the bundle is sold at a discount to the sum of parts.
| SKU | Standalone Price | % of Standalone Total | Allocated Revenue ($80 bundle) |
|---|---|---|---|
| 12oz coffee bag | $24 | 36.4% | $29.09 |
| Ceramic mug | $30 | 45.4% | $36.36 |
| Branded scoop | $12 | 18.2% | $14.55 |
| Total | $66 | 100% | $80.00 |
The "free" scoop is not free in the books. It earns $14.55 in revenue when it ships. The coffee and mug earn less than their list prices because the bundle discount is spread across all three.
Journal entry when the bundle ships
Across the 100+ Shopify stores we close books for, this is the single biggest fix we make when onboarding from a previous bookkeeper. Bundles get posted as one lump to a generic Revenue account, gross margin by product category becomes meaningless, and inventory counts drift. Bookkeep can automate the allocation if the component map is set up correctly.
Takeaway: every bundle needs a SKU-level allocation rule before the order can hit revenue. Without it, gross margin reporting by product line is fiction.
7Recognize revenue when each obligation is satisfied (Step 5)
Revenue hits the P&L when control of the product transfers to the customer. For Shopify DTC, that is almost always the ship date — when the carrier scans the package. Not the order date. Not the payment capture date. The fulfillment event.
| Order Type | Recognition Trigger | Source of Truth |
|---|---|---|
| Standard order | Ship date | Shopify Fulfillment event / Shippo scan |
| Pre-order | Actual ship date (weeks later) | Shippo / ShipBob fulfillment |
| Subscription box | Each month's ship date | Recharge fulfillment + Shippo |
| Bundle | Ship date (all components together) | Shopify Fulfillment event |
| Gift card sale | Redemption date | Shopify gift card redemption report |
| Digital product | Download or access date | Shopify Digital Downloads |
Gift card example
A customer buys a $100 Shopify gift card on December 15. The recipient redeems it on February 3 for a $90 sweater plus $10 toward shipping. No revenue is recognized in December. The full $100 sits as a Gift Card Liability. On February 3, $90 becomes Apparel Revenue and $10 becomes Shipping Revenue when the sweater ships.
Brands with material gift card programs also need a breakage policy — the portion of unredeemed balances eventually recognized as revenue based on historical patterns. Most Shopify brands under $10M revenue don't accrue breakage formally, but auditors will ask about it once the liability gets large. See our Revenue Recognition ASC 606 for Shopify DTC Brands guide for the breakage methodology.
Takeaway: the ship date is the recognition trigger for physical product. Wire your bookkeeping tool to fulfillment data, not order data.
8How to operationalize the revenue recognition 5 steps in your stack
The five steps are concept. Running them every day across thousands of Shopify orders requires the right plumbing. Here is the setup we use at Ottit across the brands we serve.
- Connect Shopify to Bookkeep for daily summary journal entries — Bookkeep handles the deferred revenue logic for pre-orders and gift cards natively
- Map every bundle SKU to its component SKUs with standalone selling prices in your rev rec tool
- Pipe Recharge billing and ship events separately — billing creates deferred revenue, ship events release it
- Use fulfillment data from Shopify or your 3PL as the recognition trigger, not order data
- Maintain a returns reserve account and true it up monthly using Shopify's actual return rate by category
- Reconcile Shopify Payments payouts in QuickBooks against the daily Bookkeep journal — see the Shopify Help Center guide to payouts for the payout timing and our QBO setup playbook for the reconciliation pattern
You will know this worked when your P&L revenue matches shipped orders for the period, deferred revenue matches the dollar value of unshipped pre-orders plus unredeemed gift cards, and gross margin by product category is stable month over month.
Tooling comparison: how Shopify revenue posts to the GL
There are three common patterns for getting Shopify revenue into QuickBooks or Xero. Each handles ASC 606 differently. We lead with Bookkeep for the rev rec scenarios in this article because it natively handles deferred revenue and gift card liabilities.
| Approach | ASC 606 handling | Deferred revenue support | Best for |
|---|---|---|---|
| Bookkeep (partner) | Daily summary journal with rev rec logic built in | Native pre-order, subscription, gift card | Shopify brands needing GAAP-clean books |
| Manual journal entries | Depends on bookkeeper discipline | Manual reconciliation each month | Sub-$500K stores with simple SKUs |
| Direct Shopify-to-QBO sync | Order-date posting, no rev rec | Not handled | Cash basis only; not GAAP |
9Common mistakes Shopify brands make with the 5 steps
- Recognizing revenue at order date instead of ship date. Cash basis books do this. Accrual books cannot. Fix by tying the journal to fulfillment events, not checkout events.
- Treating bundle SKUs as a single line of revenue. Breaks Step 2 and Step 4. Fix with a component map and allocated revenue accounts by category.
- Booking gift card sales to revenue immediately. They are a liability until redeemed. Fix by routing all gift card sales to a Gift Card Liability account.
- Allocating bundle discounts entirely to one SKU. GAAP requires proportional allocation across all performance obligations. Fix by allocating based on standalone selling prices.
- Ignoring shipping revenue as a performance obligation. Customer-paid shipping is recognized when the product ships, same as the product itself. Don't park it in a contra account.
- Skipping the returns reserve. A brand with a 12% return rate that books 100% of revenue at ship date will overstate revenue and gross profit every month.
10Troubleshooting the 5-step setup
Deferred revenue keeps growing and never clears
This usually means pre-orders or subscriptions are creating deferred revenue but ship events are not releasing it. Check that fulfillment webhooks are firing into your rev rec tool. In Bookkeep, the daily summary should show a debit to Deferred Revenue equal to the value of orders shipped that day. If that debit is missing, fulfillment data isn't connected.
Revenue total doesn't match Shopify's sales report
Shopify's sales report is order-date based. Your accrual P&L is ship-date based. The two will only match if every order in the period also shipped in the period. Expect a timing difference equal to your in-transit and pre-order backlog. Reconcile by pulling a Shopify Fulfillments by Date report and matching to revenue accounts.
Bundle gross margin looks wrong
Almost always a Step 4 allocation issue. Pull a sample bundle order and trace the journal entry. If 100% of the revenue posted to one product category, the component map is missing or wrong. Fix the map and rerun the journal for the period. See Shopify COGS Accounting: The Practitioner's Guide for matching COGS allocation.
Gift card liability never goes down
Two causes. Either redemptions are being posted as new sales (double-counting cash) or the redemption journal is hitting Revenue without clearing the liability. The correct entry on redemption is Dr. Gift Card Liability / Cr. Revenue at ship date. If the liability is stale for more than 24 months, the brand should also evaluate a breakage policy.
11Sources and references
- FASB ASC 606 (Revenue from Contracts with Customers) — the governing standard for the 5-step model
- the Shopify Help Center guide to payouts — payout timing and reconciliation reference for tying revenue to cash