returns-refund-policy

Automate your return and refund process with configurable return windows, restocking fees, and rule-based approval logic for each product type

11 stars

Best use case

returns-refund-policy is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Automate your return and refund process with configurable return windows, restocking fees, and rule-based approval logic for each product type

Teams using returns-refund-policy should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/returns-refund-policy/SKILL.md --create-dirs "https://raw.githubusercontent.com/finsilabs/awesome-ecommerce-skills/main/skills/business-operations/returns-refund-policy/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/returns-refund-policy/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How returns-refund-policy Compares

Feature / Agentreturns-refund-policyStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Automate your return and refund process with configurable return windows, restocking fees, and rule-based approval logic for each product type

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Returns & Refund Policy Engine

## Overview

A returns and refund policy engine enforces your rules automatically: different return windows per product category, restocking fees for specific item types, final-sale exclusions, and extended windows for loyalty members. This prevents your customer service team from manually evaluating every return request and ensures consistent policy enforcement. Most platforms can implement these rules through their returns apps combined with product tags and customer segments.

## When to Use This Skill

- When your return logic is inconsistent because it's handled case-by-case by customer service
- When you need different return windows for different product categories (electronics vs. apparel vs. consumables)
- When implementing tiered return policies where loyalty members get extended windows or waived restocking fees
- When building an automated approval workflow that handles most returns without human intervention
- When compliance or legal requirements mandate that return policies be auditable and version-controlled

## Core Instructions

### Step 1: Determine your platform and choose the right returns tool

| Platform | Recommended Tool | Why |
|----------|-----------------|-----|
| **Shopify** | Loop Returns or AfterShip Returns | Loop is the most feature-complete: supports per-product-type policies, restocking fees, final-sale blocking, and loyalty tier overrides |
| **WooCommerce** | ReturnGo or WooCommerce Returns and Warranty Requests | ReturnGo supports custom policy rules per product category and automated approval logic |
| **BigCommerce** | AfterShip Returns Center or Loop Returns | Both support per-category policy rules and restocking fees |
| **Custom / Headless** | Build a policy evaluation engine + Shippo for return labels | Store policies in a database; evaluate them programmatically when return requests come in |

### Step 2: Define your return policy rules

Before configuring any tool, define your policy matrix clearly:

| Product Category | Return Window | Restocking Fee | Auto-Approve | Notes |
|-----------------|---------------|----------------|--------------|-------|
| Default (apparel, accessories) | 30 days from delivery | 0% | Yes | Most items |
| Electronics | 15 days from delivery | 15% | No — manual review | Opened electronics |
| Final Sale | 0 days | — | No | No returns |
| VIP / Gold members | 60 days from delivery | 0% | Yes | Override for loyalty tier |
| Defective / Wrong item | 90 days from delivery | 0% | Yes | Customer not at fault |

### Step 3: Configure policy rules in your returns app

#### Shopify — Loop Returns

1. Install **Loop Returns** from the Shopify App Store
2. Go to Loop → Policy → Return Windows:
   - Default: 30 days
   - Click "Add Rule" → set "Product tag is 'electronics'" → return window: 15 days
   - Click "Add Rule" → set "Product tag is 'final-sale'" → return window: 0 days (no returns)
3. Tag your products accordingly in Shopify admin (Products → Tags)
4. Go to Loop → Policy → Restocking Fees:
   - Add a rule: "Product tag is 'electronics'" → restocking fee: 15%
5. Go to Loop → Policy → Customer Segments:
   - Add a rule: "Customer tag is 'gold-member' or 'vip'" → return window override: 60 days, restocking fee: 0%
6. Enable auto-approval for eligible returns in Loop → Settings → Automation: "Auto-approve returns that meet policy conditions"
7. Loop generates the return label automatically when a return is approved

**Testing your policy:**
- Use Loop's Policy Simulator (Loop → Policy → Test Policy) to verify that a hypothetical return request (product type, customer tag, days since delivery) applies the correct rule

#### WooCommerce — ReturnGo

1. Install **ReturnGo** from retgo.com (or WordPress.org)
2. Go to ReturnGo → Return Policy:
   - Set default return window: 30 days
   - Under "Custom Rules", add product-category-based rules:
     - Category "Electronics" → 15 days, 15% restocking fee, requires manual review
     - Category "Final Sale" → 0 days (no returns allowed)
3. Under "Customer Rules": add tag-based overrides:
   - Customer tag "wholesale" → 14 days, 10% restocking fee
4. Configure auto-approval: ReturnGo → Automation → enable "Auto-approve returns that match policy"
5. Test by creating a return request as a customer to verify rules apply correctly

**Configuring final-sale in WooCommerce:**
- Create a product category or tag called "final-sale"
- In ReturnGo, add a rule blocking returns for this category/tag
- On the product page, display the "Final Sale — No Returns" message using a product badge plugin

#### BigCommerce — AfterShip Returns Center

1. Install AfterShip Returns Center from the BigCommerce App Marketplace
2. Go to AfterShip → Policy:
   - Set the default return window and configure exceptions by product type
3. AfterShip's policy engine supports return windows and auto-approval rules based on product tags
4. For restocking fees: AfterShip includes restocking fee configuration in their paid plans

### Step 4: Handle return window calculation correctly

The single most important setting: the return window should start from the **delivery date**, not the order date or ship date.

**Why this matters:**
- Shipping a package takes 2–10 days depending on the service
- A 30-day return window starting from order date may leave the customer with only 20 days to actually return the item
- Most consumer protection laws (EU 14-day right of withdrawal, UK 14 days) count from delivery

**Verify this in your returns app:**
- Loop Returns: go to Loop → Settings → Return Window → "Starts from: Delivery Date" ✓
- ReturnGo: go to Settings → Policy → "Return window starts from: Delivered date" ✓
- AfterShip: go to Settings → Return Policy → "Start date: Order delivered date" ✓

If your returns app doesn't have tracking integration to detect delivery, use "Order Date + carrier average transit time" as an approximation.

### Step 5: Communicate policies clearly

1. **Returns page:** Create a dedicated `/returns` or `/return-policy` page with your policy matrix in a table format — customers reference this before purchasing
2. **Product pages:** Show a brief returns statement near the "Add to Cart" button: "30-day free returns" or "Final Sale — No Returns" for final sale items
3. **Order confirmation email:** Include a link to your returns page and a brief "30-day returns" statement
4. **Return window expiry reminder:** Set up an automated email 7 days before a customer's return window closes — Loop and AfterShip both support this

### Step 6: Custom / Headless — policy evaluation logic

```typescript
// Return policy rules stored in database and evaluated programmatically
interface ReturnPolicy {
  id: string;
  name: string;
  priority: number;           // higher = evaluated first
  conditions: {
    productTags?: string[];   // match any of these tags
    customerTags?: string[];  // match any of these customer tags
    orderTags?: string[];     // e.g., ['final-sale']
  };
  windowDays: number;         // 0 = no returns allowed
  restockingFeePct: number;   // 0–100
  autoApprove: boolean;
}

async function evaluateReturnEligibility(params: {
  orderId: string;
  productId: string;
  customerId: string;
  returnReason: string;
  deliveredAt: Date;
}): Promise<{
  eligible: boolean;
  policy: ReturnPolicy | null;
  restockingFeeCents: number;
  requiresManualReview: boolean;
  daysRemaining: number;
  reason?: string;
}> {
  const order = await db.orders.findById(params.orderId);
  const product = await db.products.findById(params.productId, { include: ['tags'] });
  const customer = await db.customers.findById(params.customerId, { include: ['tags'] });

  // Find highest-priority matching policy
  const policies = await db.returnPolicies.findAll({ is_active: true }, { orderBy: ['priority', 'desc'] });
  const policy = policies.find(p => {
    const productMatch = !p.conditions.productTags?.length ||
      p.conditions.productTags.some(tag => product.tags.includes(tag));
    const customerMatch = !p.conditions.customerTags?.length ||
      p.conditions.customerTags.some(tag => customer.tags.includes(tag));
    const orderMatch = !p.conditions.orderTags?.length ||
      p.conditions.orderTags.some(tag => order.tags?.includes(tag));
    return productMatch && customerMatch && orderMatch;
  }) ?? null;

  if (!policy || policy.windowDays === 0) {
    return { eligible: false, policy, restockingFeeCents: 0, requiresManualReview: false, daysRemaining: 0, reason: 'FINAL_SALE_OR_NO_POLICY' };
  }

  // Calculate days since delivery
  const daysSinceDelivery = Math.floor((Date.now() - params.deliveredAt.getTime()) / 86400000);
  const daysRemaining = policy.windowDays - daysSinceDelivery;

  if (daysRemaining < 0) {
    return { eligible: false, policy, restockingFeeCents: 0, requiresManualReview: false, daysRemaining: 0, reason: 'WINDOW_EXPIRED' };
  }

  // Calculate restocking fee on the item's original price
  const orderLine = await db.orderLines.findOne({ order_id: params.orderId, product_id: params.productId });
  const itemValueCents = orderLine.unit_price_cents * orderLine.quantity;
  const restockingFeeCents = Math.round(itemValueCents * (policy.restockingFeePct / 100));

  return {
    eligible: true,
    policy,
    restockingFeeCents,
    requiresManualReview: !policy.autoApprove,
    daysRemaining,
  };
}
```

## Best Practices

- **Start the return window from delivery date, not order date** — this is more fair to customers, reduces disputes, and aligns with consumer protection laws in most jurisdictions
- **Version every policy change** — when you update a return policy, log the old policy with a timestamp; apply the policy that was in effect at the time of purchase when a customer files a return
- **Display restocking fees before the customer confirms the return** — show "A 15% restocking fee ($12.75) will be deducted from your refund" during the return initiation flow, not after
- **Cap auto-approval by refund value** — even with auto-approval enabled, route returns over $500 to manual review to catch potential fraud
- **Notify customers proactively about expiring windows** — a "Your 30-day return window closes in 7 days" email for recent purchases reduces frustrated customers who missed the window

## Common Pitfalls

| Problem | Solution |
|---------|----------|
| Return window calculated from order date instead of delivery date | Check your returns app settings explicitly for "return window starts from" — default in some tools is order date; change to delivery date |
| Multiple policies match and the wrong one applies | Sort by `priority DESC` and take the first match; document the priority hierarchy in your admin; test edge cases (VIP member buying electronics) |
| Customer disputes restocking fee | Show the fee amount and the policy name ("Electronics Policy — 15% restocking fee") in the return confirmation email so customers have documentation |
| Final sale tag not applied consistently | Create a process: every product added to a sale must have the "final-sale" tag applied; audit monthly using a product tag report |

## Related Skills

- @returns-management
- @order-management-system
- @b2b-commerce

Related Skills

returns-management

11
from finsilabs/awesome-ecommerce-skills

Process returns end to end — generate prepaid labels, apply refund or exchange logic, update inventory, and notify customers automatically

wishlist-save-for-later

11
from finsilabs/awesome-ecommerce-skills

Let shoppers save products to a wishlist, share it with friends, and get notified when saved items come back in stock or drop in price

storefront-theming

11
from finsilabs/awesome-ecommerce-skills

Build a themeable storefront with design tokens and CSS custom properties that supports white-labeling, multi-brand variants, and dark mode

search-autocomplete

11
from finsilabs/awesome-ecommerce-skills

Speed up product discovery with instant search suggestions, fuzzy typo matching, and category-aware results powered by Algolia or Elasticsearch

responsive-storefront

11
from finsilabs/awesome-ecommerce-skills

Build a mobile-first storefront with thumb-friendly navigation, sticky add-to-cart buttons, and touch-optimized components for high mobile conversion

recently-viewed-products

11
from finsilabs/awesome-ecommerce-skills

Show shoppers the products they recently browsed using browser storage so they can easily pick up where they left off on your store

quick-view-modal

11
from finsilabs/awesome-ecommerce-skills

Let shoppers preview product details and add items to cart from the listing page without navigating away, reducing friction in the shopping flow

product-page-design

11
from finsilabs/awesome-ecommerce-skills

Design high-converting product detail pages with image galleries, variant selectors, social proof, and clear calls-to-action that drive add-to-cart

product-comparison

11
from finsilabs/awesome-ecommerce-skills

Let shoppers select multiple products and compare them side-by-side in a table with highlighted differences to help them make the right buying decision

mega-menu-builder

11
from finsilabs/awesome-ecommerce-skills

Build a rich navigation mega menu with product images, category highlights, featured banners, and keyboard-accessible dropdowns for large catalogs

image-zoom-360

11
from finsilabs/awesome-ecommerce-skills

Boost product confidence with high-res image zoom, 360-degree spin views, and inline video so shoppers can examine products closely before buying

faceted-navigation

11
from finsilabs/awesome-ecommerce-skills

Let shoppers filter products by multiple attributes simultaneously with URL-shareable filter state, instant results, and mobile-friendly controls