Cases/ E-commerce/ Pricing

What the manager sees: one screen for four channels

Channel pricing — the automation under the hood

No M code, no API. The manager opens one file, clicks "Refresh", grabs a coffee for 5 minutes, then spends 20 minutes eyeballing the list — and prices on four channels are updated all at once.

Power Query in M, target-price math in Excel formulas, a synchronous export into 4 templates. No manual template downloads from back-offices — the API does it all in one pass.

Channels · pricing RRP control 4 channels Power Query · M Channel APIs delivered in 5–6 mo
Industry Import and wholesale distribution of professional cosmetics · 4 channels with different fees and upload formats · brand RRP policy
Driver's seat Told from the perspective of the manager who works with the product every day. Engineering detail — the toggle in the top-right corner.
Under the hood The engineering side: M code, formulas, architecture. To see the same through the user's eyes — the toggle in the top-right corner.
Time per cycle 15–30 min ▼ was 1–2 hours per channel
Channels at once 4 ▲ in sync
Manual downloads 0 ▲ the API pulls it all
RRP check auto ▲ green / amber / red

01How it worked before us

The pricing manager used to keep this schedule: Monday — Shopify, Wednesday — Amazon, Friday — Etsy, Walmart "whenever I get to it". Each channel took 1–2 hours: download the template from the back-office, move it into Excel, recompute the formulas, check RRP, upload it back.

Because the days differed, prices drifted between channels. Customers found the same product on Shopify and Amazon at different prices and started asking questions. When a marketplace changed its fees, the formulas went stale, and for a couple of weeks something would inevitably be selling at a loss.

The distributor sells on four major channels: Shopify, Amazon, Etsy, Walmart. All four want their own pricing logic — each has its own set of fees, fulfillment rates, payment processing, its own penalties for different categories and dimensions. On top of that the brand enforces an RRP with an allowed deviation band.

Before our work the manager did this:

02What we built

One screen for four channels

A separate Excel file, "Auto-prices", holds the main table. One row per SKU, one column block per channel. Color coding shows at a glance which items are inside the RRP band, which are above and which below.

Shopify
in sync with the rest
Amazon
in sync with the rest
Etsy
in sync with the rest
Walmart
in sync with the rest
Auto-prices · summary screen updated May 12 · 09:42
data from channel APIs · fees and current prices in real time · synthetic data
Brand
Show only
within RRP band below RRP above RRP
SKU Brand RRP Cost Shopify Amazon Etsy Walmart
feeprice feeprice feeprice feeprice

* Price = the computed target price including each channel's fee. The dot on the left is the status against RRP.

The manager starts with the summary. If everything's green — apply. If there are ambers/reds — open the specific SKUs and decide for each: wait, change the RRP, or accept the deviation deliberately.

How the data refreshes

Channel APIsfees + current prices
Google SheetsRRP · wholesale · cost
Excel: "Refresh"~5 minutes
Prices readywith RRP check

One click. The API pulls fresh fees and current prices from all 4 back-offices, Google Sheets supplies the current RRP and costs, the formulas recompute target prices — all the manager has to do is look.

Where the manager enters data

Everything that needs editing by hand lives in Google Sheets. Not in Excel. That matters: the department head or category manager can open a browser anytime, change an RRP or a cost, and on the next refresh it flows into the model.

Google Sheets · prices and costs (fragment)
SKUPrice typeValue, $Effective date
SKU-A01RRP32.8005/15/2026
SKU-A01Wholesale18.2005/15/2026
SKU-A01Cost10.8004/01/2026
SKU-A01Min. allowed27.6005/15/2026
SKU-B01RRP52.5005/15/2026

The format is "long" — several rows per SKU (RRP, wholesale, cost, minimum). That gives flexibility: you can keep different price types independently, add new types without reworking the model. Power Query pivots it into the shape it needs.

Once the manager has checked everything — export

On hidden sheets "Export_Shopify", "Export_Amazon", "Export_Etsy", "Export_Walmart" the rows already sit in each channel's required format: correct columns, correct IDs. The manager copies the contents, opens the channel back-office, and applies them.

This is not automatic price upload to the channels. The system sends nothing without the manager — it just prepares the files automatically. The visual check stays with a human; the recomputation grind is removed entirely.

Architecture

Data sources
Compute
Export
Shopify · Amazon · Etsy · WalmartAPI: fees, current prices, listing status
Google SheetsRRP, wholesale, costs, deviation bands
Excel — hidden sheetAPI tokens per channel (API_Tokens)
Power Query · M fnCh — shared function per-channel wrappers GS → long → wide
Excel formulas target price + RRP check
4 export sheets Shopify · Amazon · Etsy · Walmart

The crucial point: no manual template downloads from back-offices. The M code pulls everything it needs over the API in one pass. Excel is where the business logic lives, not where copy-paste lives.

Channel APIs in M code

Power Query in M can make HTTP requests. Each channel has its own function: pull the token from the hidden sheet, do a GET/POST, parse the JSON, shape it into a table. All four functions are structurally similar; the shared wrapper:

// fnCh_Fees — shared fee-request function
// Takes: channel key, endpoint, params
let
    Creds = Excel.CurrentWorkbook(){[Name="API_Tokens"]}[Content],

    fnCh = (channel as text, endpoint as text, params as record) =>
        let
            token = Table.SelectRows(Creds, each [Channel]=channel){0}[Token],
            URL   = "https://api." & channel & ".../" & endpoint,
            resp  = Json.Document(
                Web.Contents(URL, [
                    Headers = [#"Authorization" = "Bearer " & token,
                               #"Content-Type"  = "application/json"],
                    Query   = params
                ])),
            table = Table.FromRecords(resp[items])
        in
            table
in
    fnCh

On top — per-channel wrappers that know their endpoints:

// Shopify_Fees — current rates per listing
let
    Source = fnCh("shopify", "v1/fees", [channelType = "online"]),
    Expand = Table.ExpandRecordColumn(Source, "fee",
                  {"transaction", "payment", "fulfillment"}),
    Types  = Table.TransformColumnTypes(Expand,
            {{"transaction", type number}, {"payment", type number}})
in
    Types

On the "Auto-prices" sheet every SKU automatically gets fresh fees — without copying tables out of a back-office.

Caching and throttling. Channels rate-limit requests. The M code uses Web.Contents with retry and pause settings. Refreshing the whole file takes 3–7 minutes — most of that is waiting on API responses, not computation.

Google Sheets — the single source of base prices

The same Google Sheet that holds the purchasing parameters (lead time, thresholds) also holds the pricing parameters. One sheet — both systems. Convenient, because the buyer and the pricing manager see the same thing.

Parameters in long format
FieldWhat it means
Price typeRRP / Wholesale / Cost / Min. allowed
ValueNumeric value in dollars
Effective dateThe date the price applies from (for deferred changes)

Power Query pivots the "long" format into "wide" — each SKU becomes a row with RRP, Wholesale, Cost and so on as columns. That feeds the Excel target-price formulas.

The target-price formula

The basic idea: the target price must cover all costs and leave the target margin without breaking the RRP band. All components are assembled on the sheet:

Target price = (Cost + Logistics + Payment + Target margin) ÷ (1 − channel fee)

As a real Excel formula:

=([@Cost]
  + [@[Logistics, $]]
  + [@[Payment, $]]
  + [@[Target margin, $]]
 ) / (1 - [@[Channel fee]])

The result is checked against the RRP band:

=IF([@[Target price]] < [@RRP] * (1 - [@[Allowed deviation]]),
       "BELOW RRP",
       IF([@[Target price]] > [@RRP],
            "ABOVE RRP",
            "IN BAND"))

The manager walks the "BELOW RRP" / "ABOVE RRP" items visually and decides what to do with them (raise the minimum allowed, change the margin, or leave it out of band deliberately).

A one-shot update of 4 channels

On the "Auto-prices" sheet each channel has its own section with its own fee column and its own output template:

Shopify
variant ID + price + compare-at
Amazon
seller_sku + price
Etsy
listing_id + price + status
Walmart
item_id + price + rate

When the manager has finished the visual check, the four "Export_*" sheets are already ready to copy. Each one is formatted strictly for upload into the matching back-office. Prices change on all four channels in sync, on the same day.

About the order of operations. First the manager visually validates the math on the "Auto-prices" sheet. Only then is "Apply" pressed — the totals are copied into the export sheets. This isn't "a bot that posts to the API on its own" — it's "a tool that prepares the files and waits for a green light".

03Timeline and outcome

StageFrom start
Agreeing the formulas, connecting the first channel API~3 mo
Connecting Amazon, Etsy, Walmart+1–2 mo
Export templates, shakedown5–6 mo
Auto-prices is the client's second module. It uses the same base as purchasing: the same Google Sheets, the same SKUs, the same refresh rhythm. The manager isn't learning a new tool — they work in the same logic.

A similar problem on your side?

Tell us — in 30 minutes we'll figure out what's possible.

view mode