Skip to content
Back to skills

Shopify Admin Top Product Performance

ASecurity

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

  • 181 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 28, 2026
businessnodeapiperformance

Works with

  • claude code
  • cursor
  • cli
  • api

Security analysis

A100/100

Scanned May 28, 2026

npx -y skills add 40RTY-ai/shopify-admin-skills --skill shopify-admin-top-product-performance --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Shopify Admin Top Product Performance?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Shopify Admin Top Product Performance
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/40rty-ai-shopify-admin-top-product-performance/badge)](https://www.skillsdirectory.com/skills/40rty-ai-shopify-admin-top-product-performance)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: shopify-admin-top-product-performance
role: conversion-optimization
description: "Rank products by revenue, units sold, and refund rate over a date range by aggregating order line items."
toolkit: shopify-admin, shopify-admin-execution
api_version: "2025-01"
graphql_operations:
  - orders:query
status: stable
compatibility: Claude Code, Cursor, Codex, Gemini CLI
---

## 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

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| store | string | yes | — | Store domain (e.g., mystore.myshopify.com) |
| format | string | no | human | Output format: `human` or `json` |
| dry_run | bool | no | false | Preview operations without executing mutations |
| date_range_start | string | yes | — | Start date in ISO 8601 (e.g., `2025-01-01`) |
| date_range_end | string | yes | — | End date in ISO 8601 (e.g., `2025-01-31`) |
| top_n | integer | no | 20 | Number of top products to show in the ranked output |
| sort_by | string | no | revenue | Ranking 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

```graphql
# 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:
```json
{
  "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:

| Rank | Product | Units Sold | Gross Revenue | Refunded Amount | Net Revenue | Refund 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
| Error | Cause | Recovery |
|-------|-------|----------|
| No orders returned | No orders in date range | Widen date range |
| `variant` is null on a line item | Product or variant was deleted | Still aggregated by title; product_id will be null |
| Rate limit (429) | Too many paginated requests | Narrow 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.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.