E-commerce URLs impact SEO, user experience, and conversion rates. Well-structured URLs help search engines understand your product catalog and help users navigate your store.
Key Takeaways
- 1Use descriptive, keyword-rich product slugs
- 2Keep category hierarchy shallow (2-3 levels max)
- 3Avoid session IDs and tracking in product URLs
- 4Implement canonical URLs for product variants
- 5Use consistent URL patterns across the site
“A product URL should serve as a permanent, canonical identifier for a product that remains stable even as product details change over time.”
Product URL Patterns
The structure of your product URLs directly affects discoverability and click-through rates in search results. You want URLs that both humans and search engines can understand at a glance. Here are patterns that work well in production.
# Good product URLs
/products/blue-running-shoes-nike-air-max
/p/SKU12345-nike-air-max-blue
/shop/shoes/nike-air-max-270-blue
# Bad product URLs
/product.php?id=12345&color=blue
/p/12345
/shop/products/p_12345_v_1?session=abc123
# Product URL components
/{category}/{product-slug}
/{product-slug} # Flat structure
/{brand}/{product-slug} # Brand-first
/p/{sku}-{product-slug} # SKU prefix for uniquenessNotice how good URLs include descriptive keywords while bad URLs rely on opaque IDs or session tokens. Including the product name helps users understand what they will see before clicking.
With product URLs established, you need a consistent approach for organizing them within categories. Category URLs create the navigational hierarchy that helps users browse your catalog.
Category URL Structure
Category URLs define how users navigate your product catalog and how search engines understand your site structure. The right pattern depends on your catalog size and how products relate to categories.
The table below compares common category URL patterns. Consider your catalog complexity when choosing an approach.
| Pattern | Example | Use Case |
|---|---|---|
| Flat | /shoes | Small catalogs |
| Hierarchical | /clothing/mens/shirts | Large catalogs |
| Brand + Category | /nike/running-shoes | Brand-focused stores |
| Attribute-based | /shoes/size-10 | Filtered views |
Implementing these patterns requires helper functions that generate consistent URLs across your application. The following code shows how to build category and product URLs programmatically.
// Generate category URL
function getCategoryUrl(category) {
const path = category.ancestors
.concat(category)
.map(c => slugify(c.name))
.join('/');
return `/${path}`;
}
// Generate product URL
function getProductUrl(product, options = {}) {
const slug = slugify(product.name);
// Include SKU for uniqueness
const base = `/p/${product.sku}-${slug}`;
// Add variant if selected
if (options.color || options.size) {
const params = new URLSearchParams();
if (options.color) params.set('color', options.color);
if (options.size) params.set('size', options.size);
return `${base}?${params}`;
}
return base;
}
// Canonical URL (without variants)
function getCanonicalUrl(product) {
return `https://shop.com/p/${product.sku}-${slugify(product.name)}`;
}These functions generate URLs with SKU prefixes for uniqueness and readable slugs for SEO. The canonical URL function strips variant parameters, ensuring search engines index the main product page.
Products often come in multiple colors, sizes, or configurations. How you handle variants in URLs affects both user experience and search engine optimization.
Handling Product Variants
Product variants present a URL design challenge. You need to let users share specific variant links while avoiding duplicate content issues in search results. Here are three common approaches.
<!-- Product with color/size variants -->
<!-- Option 1: Query parameters (recommended for SEO) -->
<link rel="canonical" href="https://shop.com/p/nike-air-max" />
<!-- Current variant -->
https://shop.com/p/nike-air-max?color=blue&size=10
<!-- Option 2: Separate URLs per variant -->
https://shop.com/p/nike-air-max-blue
https://shop.com/p/nike-air-max-red
<!-- Each needs canonical to main product or self -->
<!-- Option 3: Hash for client-side only -->
https://shop.com/p/nike-air-max#color=blue
<!-- Not indexed by search engines -->Query parameters (Option 1) are recommended for most stores because they allow sharing while maintaining a single canonical URL. Hash fragments work for client-side variant selection but are not indexed by search engines.
Beyond product pages, your checkout flow needs clean, secure URLs that do not expose sensitive information or break on navigation.
Cart & Checkout URLs
Cart and checkout URLs require special care for security and usability. Avoid exposing session data in URLs, and use POST requests for cart modifications instead of GET parameters.
# Cart URLs
/cart # Main cart
/cart?add=SKU123 # Add item (avoid, use POST)
/cart/SKU123/remove # Remove item (avoid, use POST)
# Checkout flow
/checkout # Start checkout
/checkout/shipping # Shipping step
/checkout/payment # Payment step
/checkout/confirm # Order review
/checkout/success?order=12345 # Confirmation
# Avoid exposing:
# - Session IDs in URLs
# - Customer data in URLs
# - Payment tokens in URLs
# Use POST for cart modifications
POST /api/cart/items
{
"sku": "SKU123",
"quantity": 1
}Using POST for cart modifications prevents accidental duplicate orders from browser refreshes or back button navigation. The checkout flow uses progressive paths that clearly indicate the user's position in the process.
Most e-commerce sites let users filter products by attributes like brand, color, or price. How you encode these filters in URLs affects both shareability and SEO.
Filter URLs
Filter URLs enable shareable, bookmarkable product searches. When a customer finds the perfect combination of filters, they should be able to send that exact view to someone else.
// E-commerce filter URL patterns
// Query parameters (most common)
// /shoes?brand=nike&color=blue&price=50-100&sort=price-asc
function buildFilterUrl(baseUrl, filters) {
const url = new URL(baseUrl);
Object.entries(filters).forEach(([key, value]) => {
if (Array.isArray(value)) {
// Multiple selections: ?color=blue&color=red
value.forEach(v => url.searchParams.append(key, v));
} else if (value) {
url.searchParams.set(key, value);
}
});
return url.toString();
}
// Example
const filterUrl = buildFilterUrl('https://shop.com/shoes', {
brand: ['nike', 'adidas'],
color: 'blue',
price: '50-100',
sort: 'price-asc'
});
// https://shop.com/shoes?brand=nike&brand=adidas&color=blue&price=50-100&sort=price-asc
// Path-based filters (for SEO)
// /shoes/nike/blue
// Requires server-side routing logicThis function handles multiple filter values by appending the same parameter multiple times. The resulting URL clearly shows all selected filters and can be bookmarked or shared.
All these URL patterns ultimately serve two audiences: your users and search engines. Making the right SEO choices ensures your product pages rank well while avoiding duplicate content penalties.
SEO Considerations
E-commerce sites often struggle with duplicate content from variants, filters, and pagination. The table below summarizes best practices for handling common SEO challenges.
| Element | Best Practice | Example |
|---|---|---|
| Canonical | Point variants to main product | <link rel="canonical" href="..."> |
| Pagination | Use rel="prev/next" or View All | ?page=2 |
| Filters | noindex filtered pages or canonical to unfiltered | robots: noindex |
| Out of stock | Keep URL, show status | Available for backorder |
| Discontinued | 301 redirect to similar or category | Redirect to category |
Applying these practices consistently across your store prevents search engines from wasting crawl budget on low-value pages while ensuring your best content gets indexed and ranked.