shopify-admin-exchange-vs-refund-ratio
SkillCommerce & financeRead-only: tracks what percentage of returns become exchanges vs. refunds vs. store credit — measures revenue recovery rate.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the shopify-admin-exchange-vs-refund-ratio skill
What this skill tells your AI
The instructions your AI receives, as published by 40rty-ai/shopify-admin-skills in skills/returns/shopify-admin-exchange-vs-refund-ratio/SKILL.md and read by ahel’s review.
Purpose
Analyzes return resolutions to calculate the split between exchanges (revenue retained), store credit (revenue deferred), and refunds (revenue lost). Tracks this as a revenue recovery metric over time. Read-only — no mutations.
Prerequisites
- Authenticated Shopify CLI session:
shopify store auth --store <domain> --scopes read_orders,read_returns - API scopes:
read_orders,read_returns
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| store | string | yes | — | Store domain (e.g., mystore.myshopify.com) |
| days_back | integer | no | 30 | Lookback window for return resolutions |
| compare_days_back | integer | no | 0 | Optional prior period for comparison (0 = no comparison) |
| format | string | no | human | Output format: human or json |
Safety
ℹ️ Read-only skill — no mutations are executed. Safe to run at any time.
Workflow Steps
-
OPERATION:
returns— query Inputs:query: "created_at:>='<NOW - days_back days>'",first: 250, pagination cursor Expected output: Returns withrefunds { totalRefundedSet },exchangeLineItems, and resolution status -
Categorize each return resolution:
- Exchange: return has
exchangeLineItemswith quantity > 0 - Store credit: return has
refundswith gift card or store credit payment - Refund: return has cash/card refund with no exchange
- Exchange: return has
-
OPERATION:
orders— query (ifcompare_days_back > 0) Inputs: Same logic for prior period to compute trend
GraphQL Operations
# returns:query — validated against api_version 2025-01
query ReturnResolutions($query: String!, $after: String) {
returns(first: 250, after: $after, query: $query) {
edges {
node {
id
status
createdAt
totalQuantity
order {
id
name
}
exchangeLineItems(first: 10) {
edges {
node {
id
quantity
lineItem {
variant {
id
title
}
}
}
}
}
refunds(first: 5) {
id
totalRefundedSet {
shopMoney {
amount
currencyCode
}
}
}
returnLineItems(first: 20) {
edges {
node {
refundableQuantity
returnReason
}
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
# orders:query — validated against api_version 2025-01
query OrdersInPeriod($query: String!, $after: String) {
orders(first: 250, after: $after, query: $query) {
edges {
node {
id
name
totalPriceSet {
shopMoney {
amount
currencyCode
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Session Tracking
Claude MUST emit the following output at each stage. This is mandatory.
On start, emit:
╔══════════════════════════════════════════════╗
║ SKILL: Exchange vs Refund Ratio ║
║ 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):
══════════════════════════════════════════════
EXCHANGE vs REFUND RATIO (<days_back> days)
Total returns resolved: <n>
Resolution breakdown:
Exchange (revenue kept): <n> (<pct>%)
Store credit (deferred): <n> (<pct>%)
Refund (revenue lost): <n> (<pct>%)
Revenue recovery rate: <pct>%
(exchanges + store credit as % of all returns)
Output: exchange_refund_ratio_<date>.csv
══════════════════════════════════════════════
For format: json, emit:
{
"skill": "exchange-vs-refund-ratio",
"store": "<domain>",
"period_days": 30,
"total_returns": 0,
"exchanges": { "count": 0, "pct": 0 },
"store_credit": { "count": 0, "pct": 0 },
"refunds": { "count": 0, "pct": 0 },
"revenue_recovery_rate_pct": 0,
"output_file": "exchange_refund_ratio_<date>.csv"
}
Output Format
CSV file exchange_refund_ratio_<YYYY-MM-DD>.csv with columns:
return_id, order_name, resolution_type, exchange_sku, refund_amount, currency, created_at
Error Handling
| Error | Cause | Recovery |
|---|---|---|
THROTTLED | API rate limit exceeded | Wait 2 seconds, retry up to 3 times |
| No resolved returns in window | No completed returns in period | Exit with summary: 0 returns |
| Exchange line items empty but status indicates exchange | In-progress exchange | Count as pending, exclude from ratio |
Best Practices
- A revenue recovery rate above 30% (exchanges + store credit) is generally a strong signal for fashion/apparel; set your own benchmark based on category.
- Use
compare_days_backto track whether returns policy changes (e.g., "exchange only" periods) improved the recovery rate. - Pair with
return-reason-analysis— high "wrong size" return reasons paired with low exchange rates may indicate size guidance issues in product listings. - Run before and after launching an exchange incentive (e.g., bonus store credit for exchanging instead of refunding) to measure impact.
Signals
- GitHub stars
- 187
- Forks
- 18
- Last commit
- Aug 2026
ahel review
S4info
community integration — published by 40rty-ai, not shopify
Automated review, not a security audit. Ruleset v1.
Advanced
- Catalog kind
- skill
- Gateway key
shopify-admin-exchange-vs-refund-ratio- Source
- github.com/40rty-ai/shopify-admin-skills