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.

  1. Identify the contract with the customer
  2. Identify the performance obligations in the contract
  3. Determine the transaction price
  4. Allocate the transaction price to each performance obligation
  5. 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.

TransactionCash basis timingASC 606 accrual timing
Standard order shipped same dayRevenue at paymentRevenue at ship date
Pre-order paid today, ships in 6 weeksRevenue at paymentDeferred until ship date
12-month prepaid subscriptionRevenue at payment1/12 recognized each ship
$100 gift card soldRevenue at saleLiability until redeemed
Bundle of 3 SKUsOne revenue lineAllocated across 3 SKUs
Customer-paid shippingRevenue at paymentRevenue 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.

Pre-order received (Day 1)
DRCash / Shopify Payments Clearing$60.00
CRDeferred Revenue (Liability)$60.00
Pre-order #1042 — product ships in 6 weeks

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.

ItemStandalone PriceStandalone Value?Performance Obligation?
12oz coffee bag$24YesYes
Ceramic mug$30YesYes
Branded scoop ('free')$12Yes (sold alone)Yes
Bundle SKU itself$80Not separateNo — 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.

CategoryTypical return rateNotes
Apparel and footwear10–20%Sizing drives most returns
Beauty and skincare3–6%Sample-size returns common
Supplements1–3%Often non-returnable
Food and beverage<2%Perishable, rarely returned
Home goods5–10%Damage in transit drives returns
Electronics and accessories8–15%High DOA component

Calculating transaction price on a $120 order

Order #2087 — apparel brand, 12% return rate
Gross order total$132.00
Less: WELCOME10 discount($12.00)
Less: Sales tax collected (excluded)($9.60)
Less: Expected refund reserve (12%)($13.25)
Transaction price for revenue allocation$97.15

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.

SKUStandalone Price% of Standalone TotalAllocated Revenue ($80 bundle)
12oz coffee bag$2436.4%$29.09
Ceramic mug$3045.4%$36.36
Branded scoop$1218.2%$14.55
Total$66100%$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

Bundle order shipped — recognize revenue
DRDeferred Revenue$80.00
CRRevenue — Coffee$29.09
CRRevenue — Drinkware$36.36
CRRevenue — Accessories$14.55
Starter Bundle order #3301 — allocated across 3 performance obligations

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 TypeRecognition TriggerSource of Truth
Standard orderShip dateShopify Fulfillment event / Shippo scan
Pre-orderActual ship date (weeks later)Shippo / ShipBob fulfillment
Subscription boxEach month's ship dateRecharge fulfillment + Shippo
BundleShip date (all components together)Shopify Fulfillment event
Gift card saleRedemption dateShopify gift card redemption report
Digital productDownload or access dateShopify 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.

Gift card sold (Dec 15)
DRCash / Shopify Payments$100.00
CRGift Card Liability$100.00
Gift card redeemed and product shipped (Feb 3)
DRGift Card Liability$100.00
CRRevenue — Apparel$90.00
CRRevenue — Shipping$10.00

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.

  1. Connect Shopify to Bookkeep for daily summary journal entries — Bookkeep handles the deferred revenue logic for pre-orders and gift cards natively
  2. Map every bundle SKU to its component SKUs with standalone selling prices in your rev rec tool
  3. Pipe Recharge billing and ship events separately — billing creates deferred revenue, ship events release it
  4. Use fulfillment data from Shopify or your 3PL as the recognition trigger, not order data
  5. Maintain a returns reserve account and true it up monthly using Shopify's actual return rate by category
  6. 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.

ApproachASC 606 handlingDeferred revenue supportBest for
Bookkeep (partner)Daily summary journal with rev rec logic built inNative pre-order, subscription, gift cardShopify brands needing GAAP-clean books
Manual journal entriesDepends on bookkeeper disciplineManual reconciliation each monthSub-$500K stores with simple SKUs
Direct Shopify-to-QBO syncOrder-date posting, no rev recNot handledCash 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