MerchantFlowMerchantFlow Docs
Profit & Loss

Sales Channels - Split Online and B2B Wholesale Reporting

Read your P&L as your whole business, online (D2C) orders only, or B2B wholesale only, and let MerchantFlow classify wholesale orders automatically from payment method, order tags, or Shopify draft orders.

Sales Channels

Sales channel reporting splits your numbers into online (D2C) and B2B wholesale, so a single large trade order stops distorting the metrics you use to judge paid acquisition. Every order in MerchantFlow carries a sales channel -- d2c or b2b -- and that one field decides whether the order absorbs ad spend, whether it counts toward ROAS and CAC, and which side of the split it lands on.

Wholesale revenue is still revenue: it counts in your P&L, gross profit, COGS and product performance exactly as it always did. What changes is that it no longer flatters your acquisition efficiency.

The Sales channels card

The card sits on the P&L page (Dashboard → Profit & Loss, /dashboard/pnl) with a three-way toggle:

ViewShows
AllYour whole business -- online plus B2B
OnlineD2C orders only
B2BWholesale orders only

It reads the global timeframe selector like the rest of the page, and reports the previous period alongside for deltas. Above the figures a share line reads Online X% / B2B Y% of net revenue, so you can see the mix at a glance without switching views.

What each view reports

MetricDefinition
Net revenueRevenue for the selected channel, after refunds
OrdersOrder count for that channel
AOVNet revenue divided by paid orders -- unpaid and $0 orders never enter it
RefundsRefunds attributed to that channel, including refunds that land outside the period on an order placed inside it
COGSCost of goods for the channel's orders
FulfilmentStored per-order fulfilment cost
Payment feesStored per-order payment and wire fees
DiscountsDiscounts given on the channel's orders
Gross profitNet revenue -- COGS
Contribution profitGross profit -- fulfilment -- payment fees -- ad spend
Contribution marginContribution profit as a percentage of net revenue

The cost rows are the stored per-order figures, the same ones the Orders page totals -- not a re-derivation. If an order carries a fulfilment cost or COGS override you entered by hand, this card reflects it.

Why it stops at contribution profit

The card deliberately does not show net profit or net margin. Operating expenses -- rent, salaries, software, the whole OPEX block -- have no per-channel attribution. There is no honest way to say what share of your accountant's fee belongs to wholesale. Contribution profit is the deepest line that can be split without inventing a number, so that is where the card stops. For net profit, read the whole-business P&L.

The card carries an acquisition block -- Ad spend, ROAS / MER, CPA, CAC and New customers -- and it behaves differently from everything above it:

  • In the All and Online views these read the same numbers, because their commerce side is online orders by definition, not by filter. The card labels this Measured on online orders.
  • In the B2B view they read N/A, not zero. Wholesale orders carry no acquisition ad spend, so the ratios do not apply. A zero would read as "we spent nothing and got nothing", which is a different and wrong claim.

Formulas, for the record:

ROAS / MER = Online gross revenue / Ad spend
CPA        = Ad spend / Online revenue-generating orders
CAC        = Ad spend / New online customers

All three read a dash when there was no ad spend in the period at all.

When the comparison period is missing

Your plan tier caps how far back reporting reaches, and both the selected window and the preceding one are clamped independently. If the clamp leaves no preceding period inside your entitlement, the card omits the comparison entirely rather than showing a -100% delta against a period that was never measured. Upgrade your plan for a longer history window.

How an order becomes B2B

There are three routes, and they do not compete -- a choice you make by hand always outranks automatic detection.

1. Enter it by hand

A wholesale deal that never touched your storefront goes in through New B2B order. See Manual Orders. These are b2b by construction.

2. Adjust a synced order

A distributor who checks out through your normal storefront syncs in as an ordinary online order. The Adjust order action on the Orders page flips its sales channel (along with fulfilment cost and a COGS override). Pro and Plus plans.

3. Let MerchantFlow detect it

Go to Dashboard → Settings (/dashboard/settings) and find the Wholesale Orders section. Three signals are available. They are OR'd -- any enabled signal that matches is enough -- and all three are off by default.

SignalMatches on
Detect by payment methodThe order's payment method appears in your list. Default list: manual. Matching ignores capitalisation
Detect by order tagThe order carries one of your tags. Default list: wholesale
Detect Shopify draft ordersThe order was created as a Shopify draft order, whatever its payment method or tags

Payment method. Shopify reports manual for a draft order collected outside checkout. If you use a named manual payment method, add its exact name -- for example Bank Deposit or Trade account. WooCommerce reports values like Direct bank transfer or cod instead, so a Woo merchant needs to add their own gateway name; the default list matches nothing there.

Order tags. Each tag is matched in full, never as a fragment. A product tag such as Wholesale Gift Box will not trip your wholesale rule.

Shopify draft orders. This one catches what the other two miss. A merchant closing deals as draft orders at a trade show often has drafts that pre-date their wholesale tag and were collected through a named manual gateway that is not in the payment-method list. Neither of the first two signals can see those. This signal reads the order's own Shopify provenance instead, so it classifies them regardless. Ordinary storefront checkouts are never affected.

Your manual choices are permanent

MerchantFlow records whether a sales channel was set automatically or by a person, and automatic detection never overwrites a human decision, in either direction. If you mark a manual-payment order back to online, it stays online through every later detection sweep.

The same rule governs turning detection off: doing so reverts only the orders detection itself classified. Anything you set by hand keeps your choice.

Changing a signal reclassifies your history

Enabling or disabling any signal reclassifies your whole order history and rebuilds the affected margins in the background. The settings page says so when you save, and your figures update shortly afterwards.

That background pass is not cosmetic. Moving an order across the channel boundary changes the ad-spend allocation of every other order on the same day, because the per-order allocation splits each day's spend across the online orders that day. That is also why the signals default to off -- they can never activate silently on a deploy.

What B2B orders are excluded from

Beyond the acquisition ratios above, a b2b order is kept out of:

  • Ad spend allocation, on both sides. It neither absorbs a share of the day's spend nor dilutes the per-order figure your online orders divide
  • Customer, LTV and cohort reporting. A manual B2B order stores no customer identity, so a wholesale buyer never lands in Customer LTV or Cohort Analysis
  • The new-customer count. Acquisition keys on a customer's first online order. A buyer whose first purchase was wholesale in January and whose first online order is in March is acquired in March -- the January order never entered the calculation

What still includes B2B

Everything that describes the business rather than paid acquisition:

Revenue, total orders, net profit, net margin, contribution margin, the P&L itself, COGS, fulfilment, payment fees, refunds, discounts, expenses, and every whole-business tile. Ad spend is always your actual ad-platform total -- it is never scaled down because some revenue was wholesale.

Common questions

Does turning on detection change my revenue or profit? No. Reclassifying an order moves it between channels and out of the acquisition ratios; it does not change what it sold for or what it cost. Tenant-level P&L totals are unaffected by definition, because ad spend is sourced from your ad platforms' daily totals rather than by summing per-order allocations. Only the distribution moves.

My ROAS dropped after I enabled wholesale detection. Is that a bug? It is the fix. A wholesale order was previously inflating the ROAS numerator while contributing no ad spend. With $10k online and $20k B2B on $2k of spend, ROAS read 15x; it now reads 5x, which is what your paid acquisition actually returned.

Can I see the split on pages other than the P&L? The card is the dedicated split. The Orders page has its own Order type filter (All / Online / B2B) for working order by order. Elsewhere the channel rule is applied automatically -- acquisition metrics are online-only everywhere they appear.

Why is the acquisition block N/A instead of 0 in the B2B view? Because zero would be a claim, and a false one. Wholesale carries no acquisition spend, so the ratio has no meaning rather than a value of nothing.

Do I need a particular plan for the Sales channels card? No. The card is available to anyone who can view the dashboard. Your plan tier only limits how far back the date range can reach, the same as everywhere else.

Last updated: September 16, 2026

Last updated on

On this page