agentsclimarketplace

Shopify admin top product performance

Skill 40RTY-ai/shopify-admin-skills/skills/conversion-optimization/shopify-admin-top-product-performance

Rank products by revenue, units sold, and refund rate over a date range by aggregating order line items.From its SKILL.md

Install
npx -y skills add 40RTY-ai/shopify-admin-skills --skill shopify-admin-top-product-performance

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

6.6 KB, as published. Nobody here has run it

Purpose

Ranks products by revenue, units sold, and refund rate for a given date range by aggregating order line items and refund line items across all orders in the period. Useful for identifying top performers and products with high refund rates. Read-only — no mutations are executed.

Prerequisites

  • Authenticated Shopify CLI session: shopify auth login --store <domain>
  • API scopes: read_orders

Parameters

ParameterTypeRequiredDefaultDescription
storestringyes—Store domain (e.g., mystore.myshopify.com)
formatstringnohumanOutput format: human or json
dry_runboolnofalsePreview operations without executing mutations
date_range_startstringyes—Start date in ISO 8601 (e.g., 2025-01-01)
date_range_endstringyes—End date in ISO 8601 (e.g., 2025-01-31)
top_nintegerno20Number of top products to show in the ranked output
sort_bystringnorevenueRanking metric: revenue, units, or refund_rate

Workflow Steps

  1. OPERATION: orders — query Inputs: first: 250, query: "created_at:>='<date_range_start>' created_at:<='<date_range_end>'", pagination cursor Expected output: All orders in range with line items (title, quantity, originalTotalSet, refundableQuantity) and refund line items; paginate until hasNextPage: false; aggregate in-memory per product: sum originalTotalSet for gross revenue, sum refund amounts for net revenue, sum quantities for units sold, compute refund rate

GraphQL Operations

# orders:query (for product revenue) — validated against api_version 2025-01
query OrdersForProductPerformance($first: Int!, $after: String, $query: String) {
  orders(first: $first, after: $after, query: $query) {
    edges {
      node {
        id
        createdAt
        lineItems(first: 50) {
          edges {
            node {
              title
              quantity
              variant {
                id
                sku
                product {
                  id
                  title
                }
              }
              originalTotalSet {
                shopMoney { amount currencyCode }
              }
              refundableQuantity
            }
          }
        }
        refunds {
          refundLineItems(first: 50) {
            edges {
              node {
                quantity
                lineItem {
                  variant {
                    id
                    product { id title }
                  }
                }
                subtotalSet {
                  shopMoney { amount currencyCode }
                }
              }
            }
          }
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Session Tracking

Claude MUST emit the following output at each stage. This is mandatory.

On start, emit:

╔══════════════════════════════════════════════╗
║  SKILL: top-product-performance              ║
║  Store: <store domain>                       ║
║  Started: <YYYY-MM-DD HH:MM UTC>             ║
╚══════════════════════════════════════════════╝

After each step, emit:

[N/TOTAL] <QUERY|MUTATION>  <OperationName>
          → Params: <brief summary of key inputs>
          → Result: <count or outcome>

On completion, emit:

For format: human (default):

══════════════════════════════════════════════
OUTCOME SUMMARY
  Orders processed:   <n>
  Products ranked:    <n>
  Date range:         <start> to <end>
  Sort by:            <revenue|units|refund_rate>
  Errors:             0
  Output:             none
══════════════════════════════════════════════

For format: json, emit:

{
  "skill": "top-product-performance",
  "store": "<domain>",
  "started_at": "<ISO8601>",
  "completed_at": "<ISO8601>",
  "dry_run": false,
  "steps": [
    { "step": 1, "operation": "OrdersForProductPerformance", "type": "query", "params_summary": "<date_range_start> to <date_range_end>", "result_summary": "<n> orders processed", "skipped": false }
  ],
  "outcome": {
    "orders_processed": 0,
    "products_ranked": 0,
    "date_range_start": "<date_range_start>",
    "date_range_end": "<date_range_end>",
    "sort_by": "revenue",
    "results": [],
    "errors": 0,
    "output_file": null
  }
}

Output Format

Ranked table displayed inline (no CSV), truncated to top_n entries:

RankProductUnits SoldGross RevenueRefunded AmountNet RevenueRefund Rate %
1..................

For format: json, results is an array of objects with keys: rank, product_id, product_title, units_sold, gross_revenue, refunded_amount, net_revenue, refund_rate_pct.

Error Handling

ErrorCauseRecovery
No orders returnedNo orders in date rangeWiden date range
variant is null on a line itemProduct or variant was deletedStill aggregated by title; product_id will be null
Rate limit (429)Too many paginated requestsNarrow date range

Best Practices

  1. For stores with many orders, use a 30-day window first. Wider windows paginate more aggressively and take longer.
  2. sort_by: refund_rate highlights products with quality or expectation issues — a refund rate above 10% is worth investigating.
  3. Revenue figures are gross (before refunds) and net (after refunds) — use net revenue for accurate profitability ranking.
  4. Products that have been deleted will still appear if they were purchased in the date range — they show with product_id: null and their title from the order line item.
  5. Combine with discount-ab-analysis to see which discount codes drove the most revenue for your top products.

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.