ds@mcpanalytics.aiEmail your data and your question and get an answer about your own data, with the method shown.Email your data and question. Get an answer.

How to Use Sales Performance in Amazon: Step-by-Step Tutorial

By MCP Analytics Team | Published , updated

Category: Amazon Analytics | Difficulty: Beginner to Intermediate

Introduction to Sales Performance Analysis

Analyzing your Amazon sales shows whether sales are growing, how FBA (Fulfilled by Amazon) orders compare with merchant-fulfilled (FBM) orders, and what a typical order is worth. This tutorial answers those three questions with pandas on an order export, and shows the definition behind every number.

The figures in every output block come from a synthetic data set generated for this tutorial (about 2,300 orders over nine months), not from a real seller, so your numbers will differ. That larger file is not included here, so the next part gives you a small one you can run yourself.

Try It First on 12 Made-Up Order Lines

This is a synthetic file, not real seller data. Save it as orders.csv. It has 12 lines from 10 orders. Order A003 is cancelled, and orders A001 and A006 have two lines each.

order_id,order_date,order_status,item_price,quantity,fulfillment,sku
A001,2025-01-05,Shipped,20.00,2,FBA,SKU-A
A001,2025-01-05,Shipped,15.00,1,FBA,SKU-B
A002,2025-01-12,Shipped,30.00,1,FBM,SKU-C
A003,2025-01-20,Cancelled,25.00,1,FBA,SKU-A
A004,2025-02-03,Shipped,20.00,3,FBA,SKU-A
A005,2025-02-10,Shipped,18.00,1,FBM,SKU-B
A006,2025-02-18,Shipped,40.00,1,FBA,SKU-D
A006,2025-02-18,Shipped,12.00,2,FBA,SKU-E
A007,2025-03-02,Shipped,22.00,2,FBM,SKU-C
A008,2025-03-09,Shipped,35.00,1,FBA,SKU-D
A009,2025-03-15,Shipped,20.00,1,FBA,SKU-A
A010,2025-03-27,Shipped,28.00,2,FBM,SKU-B

Run the Step 1, Step 2 and Step 3 code blocks below on this file, in that order. Then run one more line to get the average line: print(f"Average line revenue: ${sold['revenue'].mean():.2f}"). The outputs print in this order (blank lines are added here between the blocks):

            revenue  orders  units   aov  growth_pct
order_date                                          
2025-01        85.0       2      4  42.5         NaN
2025-02       142.0       3      7  47.3        67.1
2025-03       155.0       4      6  38.8         9.2
Average daily revenue: $42.44

             orders  revenue  units  order_share_pct  revenue_share_pct   aov
fulfillment                                                                  
FBA               5    234.0     11            55.56              61.26  46.8
FBM               4    148.0      6            44.44              38.74  37.0
FBA AOV minus FBM AOV: $9.80 (95% bootstrap interval $-10.50 to $29.10)

Orders: 9   AOV (mean): $42.44   median: $44.00   75th percentile: $56.00
revenue
under $25    22.2
$25-$50      33.3
$50-$100     44.4
over $100     0.0

Average line revenue: $34.73

Three things to notice. The cancelled order is left out, so January has 2 orders, not 3. The average order is $42.44 but the average line is $34.73, because two orders have two lines. That is why AOV divides by orders. With 9 orders the bootstrap interval in Step 2 runs from $-10.50 to $29.10, so it cannot tell whether the $9.80 gap is real. A file this small cannot support that conclusion. The +67.1% growth in February is large only because January is small.

Prerequisites and Data Requirements

What You'll Need Before Starting

  • An order export from your Amazon account as a CSV with one row per order line. Report names and menus change, so follow Seller Central's current help for exporting orders
  • Several months of history, so that seasonal swings do not look like trends. Compare the same months across years if you have them
  • Python with pandas and NumPy, or a spreadsheet if you rebuild the same steps there

Data Fields You Should Have

The code expects these column names, so rename the ones in your report to match:

  • order_id, order_date, order_status
  • item_price and quantity (price is per unit)
  • fulfillment with the values FBA and FBM (your report's column and values will be named differently; map them)
  • sku

The code counts "Shipped" lines as sales and leaves out cancelled ones. If your report uses other status words, change that one line.

Tip: Check that your data is complete before analyzing it: duplicated orders, missing dates and invalid quantities all change the totals.

What You'll Accomplish

By following this tutorial, you will:

  1. Total revenue and orders by month and compute month-over-month growth
  2. Compare FBA and merchant-fulfilled orders, with an interval for the AOV gap
  3. Calculate average order value correctly, per order and not per line, and read its distribution
  4. Know which conclusions the data supports and which need more evidence

Step 1: What is My Amazon Revenue Trend?

1Analyzing Revenue Over Time

Your revenue trend shows whether sales are growing, flat or falling. This code keeps shipped lines, adds up revenue, distinct orders and units by month, and computes growth from one month to the next. AOV here is revenue divided by the number of distinct orders: an order with several lines counts once.

import numpy as np
import pandas as pd

orders = pd.read_csv("orders.csv", parse_dates=["order_date"])
sold = orders[orders["order_status"] == "Shipped"].copy()      # cancelled lines are not sales
sold["revenue"] = sold["item_price"] * sold["quantity"]

monthly = sold.groupby(sold["order_date"].dt.to_period("M")).agg(
    revenue=("revenue", "sum"), orders=("order_id", "nunique"), units=("quantity", "sum"))
monthly["aov"] = monthly["revenue"] / monthly["orders"]          # revenue per ORDER, not per line
monthly["growth_pct"] = monthly["revenue"].pct_change() * 100
print(monthly.round(1).to_string())
print(f"Average daily revenue: ${sold['revenue'].sum() / sold['order_date'].nunique():,.2f}")
Expected Output:
            revenue  orders  units   aov  growth_pct
order_date                                          
2025-01      9041.5     209    350  43.3         NaN
2025-02      9464.0     200    357  47.3         4.7
2025-03     10456.6     232    412  45.1        10.5
2025-04     11458.8     259    431  44.2         9.6
2025-05     11673.9     260    435  44.9         1.9
2025-06     10398.2     246    394  42.3       -10.9
2025-07     11220.4     243    415  46.2         7.9
2025-08     10226.5     247    401  41.4        -8.9
2025-09     10844.3     260    409  41.7         6.0
Average daily revenue: $352.36

Revenue rises from January to May, dips in June, and is mixed after that. Growth from month to month moves between -10.9% and +10.5%, so a single month says little about the trend. If the last month in your export is partial, its growth is not comparable with full months.

  • Growth rate: month-over-month is noisy; compare with the same month a year earlier when you have the history
  • Seasonality: recurring patterns such as a holiday peak need at least a full year to see
  • Revenue per order and per unit: track them next to revenue to see whether growth comes from more orders, higher prices or larger orders

Step 2: How Does FBA Compare to Merchant Fulfilled?

2Comparing Fulfillment Method Performance

This code groups shipped orders by fulfillment method and compares orders, revenue and AOV. It then resamples orders 2,000 times to get a bootstrap interval for the AOV difference, a rough range for the gap if the orders had come out differently. For more on the comparison, see Amazon FBA vs FBM performance.

by_ch = sold.groupby("fulfillment").agg(orders=("order_id", "nunique"), revenue=("revenue", "sum"), units=("quantity", "sum"))
by_ch["order_share_pct"] = by_ch["orders"] / by_ch["orders"].sum() * 100
by_ch["revenue_share_pct"] = by_ch["revenue"] / by_ch["revenue"].sum() * 100
by_ch["aov"] = by_ch["revenue"] / by_ch["orders"]
print(by_ch.round(2).to_string())

order_totals = sold.groupby(["order_id", "fulfillment"])["revenue"].sum().reset_index()
fba = order_totals.loc[order_totals["fulfillment"] == "FBA", "revenue"].to_numpy()
fbm = order_totals.loc[order_totals["fulfillment"] == "FBM", "revenue"].to_numpy()
rng = np.random.default_rng(5)
diff = [rng.choice(fba, len(fba)).mean() - rng.choice(fbm, len(fbm)).mean() for _ in range(2000)]
lo, hi = np.percentile(diff, [2.5, 97.5])
print(f"FBA AOV minus FBM AOV: ${fba.mean() - fbm.mean():.2f} (95% bootstrap interval ${lo:.2f} to ${hi:.2f})")
Expected Output:
             orders   revenue  units  order_share_pct  revenue_share_pct    aov
fulfillment                                                                    
FBA            1572  72907.79   2639            72.91              76.92  46.38
FBM             584  21876.47    965            27.09              23.08  37.46
FBA AOV minus FBM AOV: $8.92 (95% bootstrap interval $6.35 to $11.48)

FBA has 72.91% of orders and 76.92% of revenue; its AOV is $46.38 against $37.46 for FBM, a gap of $8.92 whose interval ($6.35 to $11.48) stays above zero. In this synthetic data the gap exists; it does not say why. A gap like this can come from which products are fulfilled each way, their prices, and how much of the catalog sits in each group, as well as from the fulfillment method itself.

What Else to Check Before Concluding Anything

  • Assortment and price: compare like products, not the whole catalog, before attributing a gap to fulfillment
  • Traffic and Buy Box: order exports do not contain sessions or Buy Box data, so conversion rate and Buy Box share need other reports
  • Costs: higher revenue is not higher profit; fees, storage and fulfillment costs differ between methods
  • Returns: return rate by method needs a returns report

Step 3: What is My Average Order Value?

3Calculating Average Order Value

Average order value (AOV) is total revenue divided by the number of orders. The correct denominator is distinct orders: averaging line revenue instead (the mean of item price times quantity over rows) gives the average line, which is lower whenever orders have several lines. The code adds line revenue up per order first.

totals = sold.groupby("order_id")["revenue"].sum()
print(f"Orders: {len(totals):,}   AOV (mean): ${totals.mean():.2f}   median: ${totals.median():.2f}   75th percentile: ${totals.quantile(.75):.2f}")
bands = pd.cut(totals, [0, 25, 50, 100, np.inf], labels=["under $25", "$25-$50", "$50-$100", "over $100"])
print((bands.value_counts(normalize=True).sort_index() * 100).round(1).to_string())
Expected Output:
Orders: 2,156   AOV (mean): $43.96   median: $34.91   75th percentile: $57.16
revenue
under $25    32.8
$25-$50      34.7
$50-$100     26.2
over $100     6.2

The mean ($43.96) is above the median ($34.91) because a minority of larger orders pulls it up. Report both, and the distribution: a mean alone hides that about a third of orders here are under $25. The bands in the code are examples; choose cutoffs that make sense for your prices.

Ways to Test a Higher AOV

These are ideas to test, not proven fixes. Measure each against revenue and margin, not AOV alone, because a higher AOV can come with fewer orders.

  1. Bundling: combine complementary products
  2. Quantity pricing: offer a discount for buying more units
  3. Upselling and cross-selling: suggest an upgrade or a related product
  4. Free-shipping threshold: where your channel allows it
Tip: Track AOV next to order count. What matters for revenue is orders times AOV, and changes that raise one can lower the other. A/B testing with statistical significance is the way to check a pricing or bundling change.

Interpreting Your Results

Read the metrics together rather than one at a time. Each scenario below is a hypothesis to investigate, not a conclusion.

Scenario 1: Growing Revenue With Declining AOV

Scenario 2: FBA Ahead of FBM

Scenario 3: Flat Revenue With Increasing AOV

Setting Targets

Start from your own baseline: the monthly revenue, AOV and order count the code printed. Choose a target for one change at a time, test it, and compare with the baseline. Targets copied from another seller's numbers do not describe your catalog.

Run It on Your Own Amazon Export

Export your Amazon orders as a CSV and upload it at MCP Analytics, then ask the question in plain language; the report names the method. Nothing connects to your Amazon account.

Try it on your data

Common Issues and Solutions

Issue 1: Inconsistent Date Formats in Export Data

Problem: Dates appear in different formats (month first or day first), so some parse wrongly.

Solution: Tell pandas the format explicitly, and check the earliest and latest dates afterwards. Dates like 03/04/2025 are ambiguous; the format that fits your marketplace's report is the one to use.

orders["order_date"] = pd.to_datetime(orders["order_date"], format="%m/%d/%Y")
print(orders["order_date"].min(), orders["order_date"].max())

Issue 2: Missing Fulfillment Method

Problem: Some orders have no fulfillment label, which skews the FBA versus FBM comparison.

Solution: Label them "Unknown", leave them out of the comparison, and report how many orders were unclassified.

Issue 3: Revenue Does Not Match Seller Central

Problem: Your total differs from what Amazon's own reports show.

Common causes:

  • Refunds and returns counted differently
  • Promotional discounts, shipping and tax included in one and not the other
  • Currency conversion on international sales
  • Time zone differences in order timestamps
  • Cancelled and pending lines included in one and not the other

Solution: Write down which of these your calculation includes (this tutorial counts shipped lines, item price times quantity, no discounts, shipping or tax) and compare with the matching Amazon report.

Issue 4: A Few Huge Orders Distort the AOV

Problem: A handful of very large or very small orders move the mean.

Solution: Report the median next to the mean, as Step 3 does. Trimming the top and bottom 1% is another option, but say that you did it.

Issue 5: Seasonality Hides the Trend

Problem: A holiday peak makes month-over-month growth hard to read.

Solution: Compare each month with the same month a year earlier, which needs at least thirteen months of history.

Next Steps with Amazon Analytics

Advanced Analysis Techniques

Related Resources

A Monthly Routine

Re-export once a month and re-run the same code, so that each month is measured the same way. Record the baseline numbers each time and compare.

Your turn

Bring your own data and the question you actually need answered.

MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai

Explore more: Amazon Seller Analytics: all tools, tutorials, and guides →

Not sure which plan? Compare plans →