Returns Management
Overview
A returns management system lets customers initiate returns self-service, generates prepaid shipping labels, processes refunds or exchanges when the item is received, and handles restocking decisions. A well-run returns process builds customer trust and can become a competitive advantage. Most platforms have solid native returns workflows or purpose-built apps that handle this without custom development.
When to Use This Skill
- When launching a self-service returns portal to reduce customer service workload
- When you need a structured RMA process with tracking numbers to prevent refund fraud
- When building logic that differentiates between "refund to original payment", "store credit", and "exchange" resolutions
- When integrating return label generation with carrier APIs (UPS, FedEx, USPS)
- When managing restocking — deciding whether returned items go back to sellable inventory or to a quarantine bin
Core Instructions
Step 1: Determine your platform and choose the right returns tool
| Platform |
Recommended Tool |
Why |
| Shopify |
Loop Returns, Returnly, or AfterShip Returns |
Loop Returns is the most popular; handles self-service portal, labels, exchanges, and store credit automatically |
| WooCommerce |
WooCommerce Returns and Warranty Requests plugin or ReturnGo |
WooCommerce's official extension handles RMA workflows; ReturnGo adds a branded self-service portal |
| BigCommerce |
AfterShip Returns Center, Loop Returns, or ReturnGo |
All three have native BigCommerce integrations with self-service portals |
| Custom / Headless |
Build an RMA system + Shippo/EasyPost for return labels |
Use Shippo's return label API; build the approval and restocking workflow on top |
Step 2: Set up the returns portal
Shopify
Option A: Loop Returns (most popular, starts free)
- Install Loop Returns from the Shopify App Store
- In Loop settings, configure your return window (e.g., 30 days from delivery), eligible resolutions (refund, exchange, store credit), and which products are returnable
- Loop creates a branded returns portal at
yourstore.com/returns — customers enter their order number and email to initiate
- Configure return reasons (wrong size, changed mind, defective, etc.) in Loop → Policy → Return Reasons
- Loop generates prepaid USPS, UPS, or FedEx return labels automatically based on your carrier settings
- Enable Instant Exchange (Loop feature) so customers can place an exchange order immediately without waiting for the return to arrive
- When a return is received and inspected, Loop can automatically process the refund and sync the inventory update back to Shopify
Option B: Shopify's built-in returns (good for simple workflows)
- On an individual order: go to Orders → [Order] → Return
- Select which items to return, the return reason, and whether to restock inventory
- Generate a prepaid return label via Shopify Shipping and email it to the customer
- When the package arrives: go back to the order → mark as received → issue refund
- Limitation: Shopify's native returns do not have a self-service customer portal — customers must contact you to initiate
WooCommerce
Using WooCommerce Returns and Warranty Requests (official extension):
- Install the plugin from WooCommerce.com (paid extension)
- Go to WooCommerce → Returns to configure: return window, eligible order statuses, allowed reasons, and notification emails
- Customers see a "Request a Return" button on their order detail page in My Account
- Each return request creates an RMA record visible in WooCommerce → Returns
- To issue a return label: integrate with ShipStation which has a "Create Return Label" button from the order view, or use Pirate Ship manually for low-volume
- When the package arrives: go to the RMA in WooCommerce → Returns → mark as received → issue refund from the original order
Using ReturnGo (branded portal, free plan available):
- Install ReturnGo from WordPress.org or their website
- ReturnGo creates a branded self-service portal and handles email notifications automatically
- Configure resolution options (refund, store credit, exchange) and carrier integrations in ReturnGo settings
BigCommerce
Using AfterShip Returns Center:
- Install AfterShip Returns Center from the BigCommerce App Marketplace
- Set up your returns portal URL (branded with your store name)
- Configure return policy rules: return window, eligible products, required reasons
- AfterShip generates prepaid return labels (USPS, UPS, FedEx) when you approve a return request
- Returns syncs status back to BigCommerce orders automatically
Using Loop Returns:
- Install from BigCommerce App Marketplace
- Same configuration as the Shopify workflow above
Step 3: Configure refund and exchange resolution logic
Regardless of platform, define your resolution options clearly before going live:
- Refund to original payment method — most straightforward; Stripe/PayPal refunds process in 5–10 business days
- Store credit — faster for customers, better for your cash flow; Loop and AfterShip support automatic store credit issuance
- Exchange — requires checking stock availability for the replacement item; Loop's Instant Exchange feature handles this automatically
Key settings to configure:
- Return window: Start the clock from delivery date, not order date (this matters — check your app's setting)
- Restocking: Decide whether returned items automatically go back to inventory or require manual inspection first. For used goods or high-value items, enable manual inspection before restocking
- Restocking fee: Configure this per product category if applicable (e.g., 15% for opened electronics)
- Final sale items: Tag final-sale products in your platform and configure the returns app to block returns on those tags
Step 4: Set up return label generation
Most returns apps generate labels automatically. For manual label creation:
Shopify
- Shopify Shipping → Create Return Label: goes directly to the carrier and creates a "return" label type (charged when the customer drops off, not when you create it)
- Available carriers: USPS, UPS, DHL (varies by region)
WooCommerce
- ShipStation: the most reliable option for return labels via WooCommerce; go to an order in ShipStation → Create Return Shipment
- Pirate Ship: manual process but the cheapest USPS rates; create a return label at pirateship.com and email it to the customer
Custom / Headless
import Shippo from 'shippo';
const shippo = Shippo(process.env.SHIPPO_API_KEY);
// Create a prepaid return label (customer sends back to warehouse)
async function createReturnLabel(params: {
customerName: string;
customerAddress: Address;
warehouseName: string;
warehouseAddress: Address;
estimatedWeightLbs: number;
}): Promise<{ trackingNumber: string; labelUrl: string }> {
const shipment = await shippo.shipment.create({
address_from: {
name: params.customerName,
street1: params.customerAddress.street1,
city: params.customerAddress.city,
state: params.customerAddress.state,
zip: params.customerAddress.zip,
country: 'US',
},
address_to: {
name: params.warehouseName,
street1: params.warehouseAddress.street1,
city: params.warehouseAddress.city,
state: params.warehouseAddress.state,
zip: params.warehouseAddress.zip,
country: 'US',
},
parcels: [{
weight: (params.estimatedWeightLbs * 16).toString(), // oz
mass_unit: 'oz',
length: '12', width: '10', height: '4',
distance_unit: 'in',
}],
async: false,
is_return: true, // marks this as a return label
});
const rate = shipment.rates.find(r => r.servicelevel.token === 'usps_priority')
?? shipment.rates[0];
const transaction = await shippo.transaction.create({
rate: rate.object_id,
label_file_type: 'PDF',
});
return {
trackingNumber: transaction.tracking_number,
labelUrl: transaction.label_url,
};
}
Best Practices
- Require label from your system, not the customer's — prepaid labels let you control carrier choice, negotiate rates, and track packages; customer-supplied labels make tracking impossible
- Segregate received returns before restocking — create a physical "returned goods" bin and a logical "quarantine" status; never auto-restock without at least a visual inspection
- Issue refunds after receiving the package — only pre-authorize refunds if you offer "instant refund" as a deliberate premium feature
- Notify customers at every status change — send emails at "label created", "package received", and "refund/exchange processed" stages; lack of communication drives "where is my refund" contacts
- Start the return window from delivery date, not order date — this is more fair to customers and reduces disputes; most returns apps support this setting
- Track return reasons — aggregate return reasons monthly and share with buying/product teams; high return rates on specific SKUs indicate a product quality or description problem
Common Pitfalls
| Problem |
Solution |
| Refund processed before return physically arrives |
Configure your returns app to trigger refunds on "package received" status, not on "return requested"; check Loop/AfterShip workflow settings |
| Restocking creates inaccurate inventory counts |
Use a quarantine step before restocking; only increment inventory after inspection confirms the item is resalable |
| Customer initiates return after window expires |
Set your platform return window clearly and ensure the returns app checks order delivery date — some apps default to order date which gives customers less time |
| Return label goes unused but was purchased |
Use "pay-on-scan" label types where available (USPS allows this via Shippo) — you're only charged when the customer drops off the package |
Related Skills
- @order-fulfillment-workflow
- @shipment-tracking
- @returns-refund-policy
- @stripe-integration
- @gift-cards
1---2name: returns-management3description: Process returns end to end — generate prepaid labels, apply refund or exchange logic, update inventory, and notify customers automatically4---56# Returns Management78## Overview910A returns management system lets customers initiate returns self-service, generates prepaid shipping labels, processes refunds or exchanges when the item is received, and handles restocking decisions. A well-run returns process builds customer trust and can become a competitive advantage. Most platforms have solid native returns workflows or purpose-built apps that handle this without custom development.1112## When to Use This Skill1314- When launching a self-service returns portal to reduce customer service workload15- When you need a structured RMA process with tracking numbers to prevent refund fraud16- When building logic that differentiates between "refund to original payment", "store credit", and "exchange" resolutions17- When integrating return label generation with carrier APIs (UPS, FedEx, USPS)18- When managing restocking — deciding whether returned items go back to sellable inventory or to a quarantine bin1920## Core Instructions2122### Step 1: Determine your platform and choose the right returns tool2324| Platform | Recommended Tool | Why |25|----------|-----------------|-----|26| **Shopify** | Loop Returns, Returnly, or AfterShip Returns | Loop Returns is the most popular; handles self-service portal, labels, exchanges, and store credit automatically |27| **WooCommerce** | WooCommerce Returns and Warranty Requests plugin or ReturnGo | WooCommerce's official extension handles RMA workflows; ReturnGo adds a branded self-service portal |28| **BigCommerce** | AfterShip Returns Center, Loop Returns, or ReturnGo | All three have native BigCommerce integrations with self-service portals |29| **Custom / Headless** | Build an RMA system + Shippo/EasyPost for return labels | Use Shippo's return label API; build the approval and restocking workflow on top |3031### Step 2: Set up the returns portal3233#### Shopify3435**Option A: Loop Returns (most popular, starts free)**36371. Install Loop Returns from the Shopify App Store382. In Loop settings, configure your return window (e.g., 30 days from delivery), eligible resolutions (refund, exchange, store credit), and which products are returnable393. Loop creates a branded returns portal at `yourstore.com/returns` — customers enter their order number and email to initiate404. Configure return reasons (wrong size, changed mind, defective, etc.) in Loop → Policy → Return Reasons415. Loop generates prepaid USPS, UPS, or FedEx return labels automatically based on your carrier settings426. Enable **Instant Exchange** (Loop feature) so customers can place an exchange order immediately without waiting for the return to arrive437. When a return is received and inspected, Loop can automatically process the refund and sync the inventory update back to Shopify4445**Option B: Shopify's built-in returns (good for simple workflows)**46471. On an individual order: go to **Orders → [Order] → Return**482. Select which items to return, the return reason, and whether to restock inventory493. Generate a prepaid return label via Shopify Shipping and email it to the customer504. When the package arrives: go back to the order → mark as received → issue refund515. Limitation: Shopify's native returns do not have a self-service customer portal — customers must contact you to initiate5253#### WooCommerce5455**Using WooCommerce Returns and Warranty Requests (official extension):**56571. Install the plugin from WooCommerce.com (paid extension)582. Go to **WooCommerce → Returns** to configure: return window, eligible order statuses, allowed reasons, and notification emails593. Customers see a "Request a Return" button on their order detail page in My Account604. Each return request creates an RMA record visible in WooCommerce → Returns615. To issue a return label: integrate with **ShipStation** which has a "Create Return Label" button from the order view, or use **Pirate Ship** manually for low-volume626. When the package arrives: go to the RMA in WooCommerce → Returns → mark as received → issue refund from the original order6364**Using ReturnGo (branded portal, free plan available):**65661. Install ReturnGo from WordPress.org or their website672. ReturnGo creates a branded self-service portal and handles email notifications automatically683. Configure resolution options (refund, store credit, exchange) and carrier integrations in ReturnGo settings6970#### BigCommerce7172**Using AfterShip Returns Center:**73741. Install AfterShip Returns Center from the BigCommerce App Marketplace752. Set up your returns portal URL (branded with your store name)763. Configure return policy rules: return window, eligible products, required reasons774. AfterShip generates prepaid return labels (USPS, UPS, FedEx) when you approve a return request785. Returns syncs status back to BigCommerce orders automatically7980**Using Loop Returns:**811. Install from BigCommerce App Marketplace822. Same configuration as the Shopify workflow above8384### Step 3: Configure refund and exchange resolution logic8586Regardless of platform, define your resolution options clearly before going live:87881. **Refund to original payment method** — most straightforward; Stripe/PayPal refunds process in 5–10 business days892. **Store credit** — faster for customers, better for your cash flow; Loop and AfterShip support automatic store credit issuance903. **Exchange** — requires checking stock availability for the replacement item; Loop's Instant Exchange feature handles this automatically9192**Key settings to configure:**9394- **Return window:** Start the clock from delivery date, not order date (this matters — check your app's setting)95- **Restocking:** Decide whether returned items automatically go back to inventory or require manual inspection first. For used goods or high-value items, enable manual inspection before restocking96- **Restocking fee:** Configure this per product category if applicable (e.g., 15% for opened electronics)97- **Final sale items:** Tag final-sale products in your platform and configure the returns app to block returns on those tags9899### Step 4: Set up return label generation100101Most returns apps generate labels automatically. For manual label creation:102103#### Shopify104105- Shopify Shipping → Create Return Label: goes directly to the carrier and creates a "return" label type (charged when the customer drops off, not when you create it)106- Available carriers: USPS, UPS, DHL (varies by region)107108#### WooCommerce109110- **ShipStation**: the most reliable option for return labels via WooCommerce; go to an order in ShipStation → Create Return Shipment111- **Pirate Ship**: manual process but the cheapest USPS rates; create a return label at pirateship.com and email it to the customer112113#### Custom / Headless114115```typescript116import Shippo from 'shippo';117const shippo = Shippo(process.env.SHIPPO_API_KEY);118119// Create a prepaid return label (customer sends back to warehouse)120async function createReturnLabel(params: {121 customerName: string;122 customerAddress: Address;123 warehouseName: string;124 warehouseAddress: Address;125 estimatedWeightLbs: number;126}): Promise<{ trackingNumber: string; labelUrl: string }> {127 const shipment = await shippo.shipment.create({128 address_from: {129 name: params.customerName,130 street1: params.customerAddress.street1,131 city: params.customerAddress.city,132 state: params.customerAddress.state,133 zip: params.customerAddress.zip,134 country: 'US',135 },136 address_to: {137 name: params.warehouseName,138 street1: params.warehouseAddress.street1,139 city: params.warehouseAddress.city,140 state: params.warehouseAddress.state,141 zip: params.warehouseAddress.zip,142 country: 'US',143 },144 parcels: [{145 weight: (params.estimatedWeightLbs * 16).toString(), // oz146 mass_unit: 'oz',147 length: '12', width: '10', height: '4',148 distance_unit: 'in',149 }],150 async: false,151 is_return: true, // marks this as a return label152 });153154 const rate = shipment.rates.find(r => r.servicelevel.token === 'usps_priority')155 ?? shipment.rates[0];156 const transaction = await shippo.transaction.create({157 rate: rate.object_id,158 label_file_type: 'PDF',159 });160161 return {162 trackingNumber: transaction.tracking_number,163 labelUrl: transaction.label_url,164 };165}166```167168## Best Practices169170- **Require label from your system, not the customer's** — prepaid labels let you control carrier choice, negotiate rates, and track packages; customer-supplied labels make tracking impossible171- **Segregate received returns before restocking** — create a physical "returned goods" bin and a logical "quarantine" status; never auto-restock without at least a visual inspection172- **Issue refunds after receiving the package** — only pre-authorize refunds if you offer "instant refund" as a deliberate premium feature173- **Notify customers at every status change** — send emails at "label created", "package received", and "refund/exchange processed" stages; lack of communication drives "where is my refund" contacts174- **Start the return window from delivery date, not order date** — this is more fair to customers and reduces disputes; most returns apps support this setting175- **Track return reasons** — aggregate return reasons monthly and share with buying/product teams; high return rates on specific SKUs indicate a product quality or description problem176177## Common Pitfalls178179| Problem | Solution |180|---------|----------|181| Refund processed before return physically arrives | Configure your returns app to trigger refunds on "package received" status, not on "return requested"; check Loop/AfterShip workflow settings |182| Restocking creates inaccurate inventory counts | Use a quarantine step before restocking; only increment inventory after inspection confirms the item is resalable |183| Customer initiates return after window expires | Set your platform return window clearly and ensure the returns app checks order delivery date — some apps default to order date which gives customers less time |184| Return label goes unused but was purchased | Use "pay-on-scan" label types where available (USPS allows this via Shippo) — you're only charged when the customer drops off the package |185186## Related Skills187188- @order-fulfillment-workflow189- @shipment-tracking190- @returns-refund-policy191- @stripe-integration192- @gift-cards