Skip to main content
Glama

Sales by product, collection or tag

get_sales_by
Read-onlyIdempotent

Product sales for the period grouped by product, product type, collection, tag or sales channel, optionally narrowed to some collections, product types, tags, title words or one sales channel. Use for any question the fixed product tools cannot answer: 'how much did the Special Prices collection sell this week', 'sales by tag', 'online vs in-store by product', 'how is product X doing' (search), or any product beyond the top ten. Per row: revenue (without VAT, before returns), returns (an ESTIMATE per group: each refund is split pro rata across its order's lines because Shopify's refund lines are not stored per product, so write 'unas', 'aproximadamente' or 'estimated' for a group's returns and its return rate, never as exact), netSales (= revenue − returns), units, orders, cost, grossProfit and marginPct (null = costs unknown, never zero), share of the filtered total, and previousNetSales with changePct against the comparison period. total counts every matching line ONCE; storeNetSales is every product line in the period, and filteredShare = total.netSales ÷ storeNetSales — that IS the answer to 'what part of sales came from X', quote it rather than dividing. overlapping true (collection, tag) = a product counts in each of its collections or tags, so rows can add up to more than the total: never sum them. A row with an empty label is 'none' (no collection, no tag, no type). collections.unmatched lists names that matched no collection and collections.available the store's real ones: retry with one, or say it does not exist. partialCollections = collections Nuira holds only part of the products of (Shopify lists more), so their figures are a floor: say so. Membership is the collection's current one, not as of each order. Revenue here is product line revenue, which is why it differs from get_summary's order revenue. Optional from and to (inclusive YYYY-MM-DD, both or neither, never after today) read another span instead of the default period. A named month, a week or two dates the operator gave MUST be sent here: without them this reads the last 30 days, which is not that month.

Input Schema

NameRequiredDescriptionDefault
byYesHow to group the sales: product, productType (Shopify's product type), collection, tag, or salesChannel (online, pos, …). By product, every row also carries `stock`: unitsNow, variants, variantsOutNow (tracked variants at 0 now), untrackedVariants (not counted by Shopify, never 'sold out') and variantsOutDuring (variants seen at 0 during the span; observations start at stockObservedSince, null before) — the read for 'do the products that sell have stock?'.
toNoLast day of the span, inclusive, as YYYY-MM-DD; not after today. Send together with `from`, or omit both to read the default 30-day period.
dirNodesc (default, biggest first) or asc (smallest first).
fromNoFirst day of the span, inclusive, as YYYY-MM-DD. Send together with `to`, or omit both to read the default 30-day period.
sortNoRow order: netSales (default), units, orders, changePct, returns (dir desc lists what is returned most; estimates per product), or netSalesChange (with compare: the money change, so dir asc lists the biggest falls first and desc the biggest rises).
tagsNoOnly products with these tags, any of them.
limitNoRows to return, 1 to 50; default 20.
searchNoOnly products whose title contains these words.
compareNoCompare every row with this period: previous (default), yoy (same dates last year) or yoyWeekday (52 weeks back). When given, each row also carries lastPeriod (the comparison's revenue, returns, units and orders), netSalesChange, revenueChange, returnsChange and returnRate (returns ÷ revenue in both periods, change in points; null in a period where refunds passed sales, which moreReturnedThanSold names as current, previous or both), volumeEffect and priceEffect (revenueChange from selling more or fewer units, and from price, discounts and mix), and shareOfChange (the row's part of the whole set's change in net sales, can pass 100% or be negative when other rows moved the other way), and totalComparison compares the whole filtered set: revenue, returns, netSales, units, orders, pricePerUnit (revenue per unit sold), volumeEffect, priceEffect and returnRate — quote them instead of subtracting.
compareToNoLast day of the named comparison period, YYYY-MM-DD.
collectionsNoOnly products in these collections (titles or handles; a part of the title is enough), any of them.
compareFromNoFirst day of a NAMED comparison period, YYYY-MM-DD, with compareTo. For 'September with October': from/to October, compareFrom/compareTo the whole of September. Takes the place of compare.
productTypesNoOnly these product types, any of them.
salesChannelNoOnly online orders, or only point-of-sale orders.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedInput schema / properties / compareFrom
      Added value: +{
      +  "description": "First day of a NAMED comparison period, YYYY-MM-DD, with compareTo. For 'September with October': from/to October, compareFrom/compareTo the whole of September. Takes the place of compare.",
      +  "format": "date",
      +  "type": "string"
      +}
    • addedInput schema / properties / compareTo
      Added value: +{
      +  "description": "Last day of the named comparison period, YYYY-MM-DD.",
      +  "format": "date",
      +  "type": "string"
      +}
  2. Changed2 schema fields changed
    • changedInput schema / properties / sort / description
      Previous value: -"Row order: netSales (default), units, orders, changePct, or netSalesChange (with compare: the money change, so dir asc lists the biggest falls first and desc the biggest rises)."New value: +"Row order: netSales (default), units, orders, changePct, returns (dir desc lists what is returned most; estimates per product), or netSalesChange (with compare: the money change, so dir asc lists the biggest falls first and desc the biggest rises)."
    • changedInput schema / properties / sort / enum
      Previous value: -[
      -  "netSales",
      -  "units",
      -  "orders",
      -  "changePct",
      -  "netSalesChange"
      -]New value: +[
      +  "netSales",
      +  "units",
      +  "orders",
      +  "changePct",
      +  "returns",
      +  "netSalesChange"
      +]
  3. Changed1 schema field changed
    • changedInput schema / properties / compare / description
      Previous value: -"Compare every row with this period: previous (default), yoy (same dates last year) or yoyWeekday (52 weeks back). When given, each row also carries the comparison period's revenue, returns, units and orders, netSalesChange, revenueChange, returnsChange and returnRate (returns ÷ revenue in both periods, change in points; above 1 means refunds of EARLIER sales exceeded this period's sales of that group — say that, never call it a rate over 100%), volumeEffect and priceEffect (revenueChange from selling more or fewer units, and from price, discounts and mix), and shareOfChange (the row's part of the whole set's change in net sales, can pass 100% or be negative when other rows moved the other way), and totalComparison compares the whole filtered set: revenue, returns, netSales, units, orders, pricePerUnit (revenue per unit sold), volumeEffect, priceEffect and returnRate — quote them instead of subtracting."New value: +"Compare every row with this period: previous (default), yoy (same dates last year) or yoyWeekday (52 weeks back). When given, each row also carries lastPeriod (the comparison's revenue, returns, units and orders), netSalesChange, revenueChange, returnsChange and returnRate (returns ÷ revenue in both periods, change in points; null in a period where refunds passed sales, which moreReturnedThanSold names as current, previous or both), volumeEffect and priceEffect (revenueChange from selling more or fewer units, and from price, discounts and mix), and shareOfChange (the row's part of the whole set's change in net sales, can pass 100% or be negative when other rows moved the other way), and totalComparison compares the whole filtered set: revenue, returns, netSales, units, orders, pricePerUnit (revenue per unit sold), volumeEffect, priceEffect and returnRate — quote them instead of subtracting."
  4. Changed1 schema field changed
    • changedInput schema / properties / compare / description
      Previous value: -"Compare every row with this period: previous (default), yoy (same dates last year) or yoyWeekday (52 weeks back). When given, each row also carries the comparison period's revenue, returns, units and orders, netSalesChange, revenueChange, returnsChange and returnRate (returns ÷ revenue in both periods, change in points; above 1 means refunds of EARLIER sales exceeded this period's sales of that group — say that, never call it a rate over 100%), and totalComparison compares the whole filtered set: revenue, returns, netSales, units, orders, pricePerUnit (revenue per unit sold) and returnRate — quote them instead of subtracting."New value: +"Compare every row with this period: previous (default), yoy (same dates last year) or yoyWeekday (52 weeks back). When given, each row also carries the comparison period's revenue, returns, units and orders, netSalesChange, revenueChange, returnsChange and returnRate (returns ÷ revenue in both periods, change in points; above 1 means refunds of EARLIER sales exceeded this period's sales of that group — say that, never call it a rate over 100%), volumeEffect and priceEffect (revenueChange from selling more or fewer units, and from price, discounts and mix), and shareOfChange (the row's part of the whole set's change in net sales, can pass 100% or be negative when other rows moved the other way), and totalComparison compares the whole filtered set: revenue, returns, netSales, units, orders, pricePerUnit (revenue per unit sold), volumeEffect, priceEffect and returnRate — quote them instead of subtracting."
  5. Changed4 schema fields changed
    • changedInput schema / properties / by / description
      Previous value: -"How to group the sales: product, productType (Shopify's product type), collection, tag, or salesChannel (online, pos, …)."New value: +"How to group the sales: product, productType (Shopify's product type), collection, tag, or salesChannel (online, pos, …). By product, every row also carries `stock`: unitsNow, variants, variantsOutNow (tracked variants at 0 now), untrackedVariants (not counted by Shopify, never 'sold out') and variantsOutDuring (variants seen at 0 during the span; observations start at stockObservedSince, null before) — the read for 'do the products that sell have stock?'."
    • changedInput schema / properties / compare / description
      Previous value: -"Compare every row with this period: previous (default), yoy (same dates last year) or yoyWeekday (52 weeks back). When given, each row also carries the comparison period's revenue, returns, units and orders, netSalesChange, revenueChange, returnsChange and returnRate (returns ÷ revenue in both periods, change in points) — quote them instead of subtracting."New value: +"Compare every row with this period: previous (default), yoy (same dates last year) or yoyWeekday (52 weeks back). When given, each row also carries the comparison period's revenue, returns, units and orders, netSalesChange, revenueChange, returnsChange and returnRate (returns ÷ revenue in both periods, change in points; above 1 means refunds of EARLIER sales exceeded this period's sales of that group — say that, never call it a rate over 100%), and totalComparison compares the whole filtered set: revenue, returns, netSales, units, orders, pricePerUnit (revenue per unit sold) and returnRate — quote them instead of subtracting."
    • changedInput schema / properties / sort / description
      Previous value: -"Row order: netSales (default), units, orders or changePct."New value: +"Row order: netSales (default), units, orders, changePct, or netSalesChange (with compare: the money change, so dir asc lists the biggest falls first and desc the biggest rises)."
    • changedInput schema / properties / sort / enum
      Previous value: -[
      -  "netSales",
      -  "units",
      -  "orders",
      -  "changePct"
      -]New value: +[
      +  "netSales",
      +  "units",
      +  "orders",
      +  "changePct",
      +  "netSalesChange"
      +]
  6. Changed1 schema field changed
    • addedInput schema / properties / compare
      Added value: +{
      +  "description": "Compare every row with this period: previous (default), yoy (same dates last year) or yoyWeekday (52 weeks back). When given, each row also carries the comparison period's revenue, returns, units and orders, netSalesChange, revenueChange, returnsChange and returnRate (returns ÷ revenue in both periods, change in points) — quote them instead of subtracting.",
      +  "enum": [
      +    "previous",
      +    "yoy",
      +    "yoyWeekday"
      +  ],
      +  "type": "string"
      +}
  7. Added

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover only the safety profile (readOnly, idempotent, non-destructive), and the description goes far beyond that: returns are a pro-rata ESTIMATE that must not be quoted as exact, marginPct null means unknown costs (never zero), overlapping collections/tags mean rows must never be summed, an empty label means 'none', partialCollections figures are a floor, and membership is current rather than as-of-order. It also pre-explains why revenue differs from get_summary and what the default period is when `from`/`to` are omitted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded well with purpose then use cases, and most sentences carry decision-relevant content. But it is a single dense wall of text with long nested parentheticals and no grouping, making it hard to scan for a 14-parameter tool; there is also a stray store-name token ("Nuira") that reads as an artifact rather than instruction.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 14-parameter aggregation tool with no output schema, the description compensates thoroughly: it enumerates every returned field (revenue, returns, netSales, units, orders, cost, grossProfit, marginPct, share, previousNetSales/changePct), explains total vs storeNetSales and filteredShare, and documents filter failure modes and comparison periods. Nothing an agent needs to invoke it correctly or interpret the response appears missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already carries the parameter documentation and the baseline is 3. The description still adds real meaning the schema does not: the consequence of omitting from/to (silent 30-day default) and the requirement to send operator-supplied dates, plus how `compare` changes each row's payload and how `sort`/`dir` interact with netSalesChange.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names the verb and resource precisely ("Product sales for the period grouped by product, product type, collection, tag or sales channel") and enumerates the five groupings from the `by` enum. It also draws the boundary against the fixed product tools and against get_summary's order-level revenue, so an agent can place it among siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use with concrete example questions ('how much did the Special Prices collection sell this week', 'online vs in-store by product'), a when-not ('use for any question the fixed product tools cannot answer'), and a hard rule that a named month/week/date pair MUST be passed or the tool silently reads the last 30 days. It even prescribes recovery when a filter matches nothing (retry with collections.available) or say it does not exist.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources