
Product Analytics
- 102 installs
- 41 repo stars
- Updated March 13, 2026
- finsilabs/awesome-ecommerce-skills
Track product performance with sell-through rates, views-to-purchase conversion, dead-stock identification, and category-level reporting.
About
Provides product-level analytics including sell-through rate, views-to-purchase conversion, dead-stock detection, and category reporting. A developer or merchandiser uses it to understand which products perform and which to discontinue.
- Sell-through and views-to-purchase conversion metrics
- Dead-stock identification and category-level reporting
Product Analytics by the numbers
- 102 all-time installs (skills.sh)
- Ranked #846 of 2,064 Data Science & ML skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill product-analyticsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 102 |
|---|---|
| repo stars | ★ 41 |
| Last updated | March 13, 2026 |
| Repository | finsilabs/awesome-ecommerce-skills ↗ |
What it does
Track product performance with sell-through rates, views-to-purchase conversion, dead-stock identification, and category-level reporting.
Files
Product Analytics
Overview
Product analytics reveals which products drive revenue, which are overstocked, and which product pages are losing shoppers before they add to cart. The core analyses — sell-through rate, dead stock identification, PDP conversion funnel, and category performance — give your buying and merchandising team the data they need to make confident reorder, markdown, and catalog decisions.
This skill guides you through running these analyses using your platform's built-in tools and dedicated apps, without building custom data pipelines.
When to Use This Skill
- When the buying team needs a weekly sell-through report to decide on reorders and markdowns
- When building a product performance dashboard for merchandisers
- When identifying dead stock that ties up capital
- When measuring which products have high views but low add-to-cart rates
- When ranking products for collection page sorting based on performance data
- When generating a catalog health report before a seasonal reset
Core Instructions
Step 1: Choose your product analytics tool by platform
| Platform | Tool | What It Provides |
|---|---|---|
| Shopify | Shopify Analytics (built-in) | Product-level revenue, units sold, sell-through (if cost entered); free |
| Shopify | Inventory Planner (App Store) | Sell-through rates, days of supply, reorder recommendations, dead stock alerts |
| Shopify | Google Analytics 4 (via Shopify's GA4 integration) | PDP views, add-to-cart rate, checkout funnel by product |
| WooCommerce | WooCommerce Analytics (built-in) | Product revenue, units sold, orders by product; free |
| WooCommerce | Metorik | Advanced product analytics including sell-through, cohort analysis by product, and dead stock reports |
| BigCommerce | BigCommerce Analytics → Merchandising (built-in) | Product revenue, units sold, and conversion rate by product |
| BigCommerce | Glew.io (App Marketplace) | Advanced sell-through, dead stock, and product lifecycle analytics |
| All platforms | Google Analytics 4 + enhanced ecommerce | Views-to-cart-to-purchase funnel by product; requires GA4 setup with ecommerce tracking |
Step 2: Analyze sell-through rate
Sell-through rate measures how much of received inventory has been sold:
Sell-through % = Units Sold / (Units Sold + Units On Hand) × 100A product at 80%+ sell-through is performing well. Below 30% after 60+ days suggests slow movement.
---
Shopify
Using Shopify Analytics: 1. Go to Analytics → Reports → Inventory sold and remaining (this is the sell-through report) 2. Set the date range to the product's launch date or the beginning of the season 3. The report shows: Units received, Units sold, Units remaining, and % sold for each variant 4. Export to CSV for detailed analysis
Using Inventory Planner: 1. Install Inventory Planner from the Shopify App Store 2. Go to Inventory Planner → Reports → Sell-Through — shows sell-through rate by product and variant 3. Go to Inventory Planner → Reports → Days of Supply — shows how many days of stock remain at current sales velocity 4. Go to Inventory Planner → Replenishment — automatically recommends reorder quantities and timing
Key sell-through benchmarks by category:
- Fashion/seasonal items: Target 70%+ sell-through by end of season; anything below 40% at season end needs markdown
- Evergreen/perennial basics: 50–70% sell-through is normal (higher in-stock availability is intentional)
- Perishables/consumables: 85%+ (low days of supply is the goal)
---
WooCommerce
Using WooCommerce Analytics: 1. Go to WooCommerce → Analytics → Products 2. Set date range to the period you want to analyze 3. View: Revenue, Quantity, Average price, Orders by product 4. Export to CSV; calculate sell-through manually by dividing quantity sold by (quantity sold + current stock)
Using Metorik: 1. Go to Metorik → Products — view all products with revenue, units sold, and refund data 2. Apply the Slow Moving filter to identify products with low recent sales relative to their stock levels 3. Create a Segment in Metorik for "products with 0 sales in the last 60 days" and monitor regularly
---
BigCommerce
1. Go to Analytics → Merchandising → Products — shows revenue, units sold, and conversion rate per product 2. Go to Analytics → Merchandising → Inventory — shows current stock levels alongside recent sales velocity 3. Install Glew.io for sell-through rate calculations and dead stock alerts with automated weekly digest emails
---
Step 3: Identify dead stock
Dead stock is inventory that has been on hand for a long time with minimal or no sales. It ties up working capital, occupies warehouse space, and often requires markdowns to liquidate.
Dead stock criteria (adjust by category):
- Fashion/seasonal: On hand 60+ days + sell-through < 20%
- Evergreen basics: On hand 120+ days + sell-through < 15%
- High-value items: On hand 90+ days + inventory value > $500
Finding dead stock by platform:
Shopify: 1. Go to Analytics → Reports → Inventory sold and remaining — filter for products with > 90 days since first available AND sell-through < 20% 2. Alternatively, install Inventory Planner → go to Reports → Excess Inventory for automated dead stock identification with capital-at-risk calculation
WooCommerce: 1. Go to WooCommerce → Analytics → Products — sort by "units sold ascending" to find products with minimal recent sales 2. Cross-reference with WooCommerce → Products → Inventory for current stock levels 3. Metorik makes this easier: go to Metorik → Products → Filter by: 0 sales in last 90 days AND stock > 0
Dead stock action guide:
| Days on Hand | Sell-Through | Recommended Action |
|---|---|---|
| 60–90 days | < 20% | 10–15% markdown; add to promotional emails |
| 91–120 days | < 15% | 20–25% markdown; feature in collections and homepage |
| 120–180 days | < 10% | 30–40% markdown; run dedicated clearance campaign |
| 180+ days | < 5% | 40–50% markdown or bundle with fast-movers; consider liquidation if markup still negative |
Step 4: Measure product page conversion (Views → ATC → Purchase)
A product with high traffic but low add-to-cart rate signals a page problem: pricing, description, images, or reviews.
Setting up product-level funnel tracking:
All platforms require Google Analytics 4 with Enhanced Ecommerce for PDP conversion tracking.
Shopify: 1. Go to Shopify → Online Store → Preferences → Google Analytics and add your GA4 Measurement ID 2. Or install Google & YouTube from the Shopify App Store (recommended — includes server-side events) 3. In GA4, go to Reports → Monetization → Ecommerce purchases → filter by item to see views, add-to-carts, and purchases per product 4. For a funnel view: go to GA4 → Explore → Funnel exploration and build a funnel: view_item → add_to_cart → begin_checkout → purchase; dimension by item_name
WooCommerce: 1. Install Google Analytics for WooCommerce by MonsterInsights or Site Kit by Google — both send WooCommerce product events to GA4 automatically 2. View product funnel the same way as Shopify in GA4
BigCommerce: 1. Go to BigCommerce → Analytics → Marketing → Connected Channels → Google Analytics and enable Enhanced Ecommerce 2. View product funnel in GA4
Key PDP conversion benchmarks:
- PDP view → Add to cart: 5–15% is typical; below 3% warrants investigation
- Add to cart → Purchase: 40–60% is typical
What low add-to-cart rate usually means:
- Price is too high relative to perceived value → A/B test price or add value (bundle, guarantee)
- Product images are poor quality or show the product unclearly → Improve photography
- Description does not address customer objections → Add FAQ section, size guide, or material details
- Reviews are low or absent → Activate review request automation
Step 5: Build a weekly catalog health report
Combine sell-through, dead stock, and conversion data into a weekly report for the buying team.
Report structure (can be a recurring Metorik digest, Inventory Planner export, or manual Shopify CSV export):
WEEKLY CATALOG HEALTH REPORT — Week of [Date]
HEADLINE METRICS
Active SKUs: 284
Dead stock count (>90 days, <15% ST): 23 SKUs ($41,200 at cost)
Low stock / reorder needed (<14 days supply): 12 SKUs
New arrivals launched this week: 8 SKUs
TOP PERFORMERS (Revenue, last 7 days)
[Product A] — $12,400 — 78% sell-through — 14 days supply remaining
[Product B] — $9,800 — 65% sell-through — 32 days supply remaining
PRODUCTS NEEDING ATTENTION
Slow movers (on hand >90 days, <20% ST):
[SKU X] — 180 days on hand — 8% ST — $4,200 inventory value — ACTION: 30% markdown
[SKU Y] — 120 days on hand — 12% ST — $2,800 inventory value — ACTION: 20% markdown
High views, low ATC (>200 views last 7 days, <3% ATC):
[Product Z] — 340 views — 1.8% ATC — Review product description and pricingBest Practices
- Report sell-through weekly, not monthly — a weekly cadence lets buyers intervene before products age into dead stock
- Always include inventory value (units × cost) in dead stock reports — a merchant cares more about $5,000 tied up in slow movers than 100 units of a $3 product
- Set different dead-stock thresholds by category — fashion items become dead stock faster (60 days) than perennial basics (180 days); configure category-specific thresholds in Inventory Planner or your reporting tool
- Use days of supply, not just inventory count — 500 units of a product selling 5/day (100 days of supply) is very different from 500 units selling 1/day (500 days); days of supply is the actionable metric
- Pair low-ATC-rate alerts with session recording — tools like Hotjar or Lucky Orange (Shopify App Store) let you watch real visitor sessions on high-traffic/low-converting product pages; often reveals issues invisible in metrics alone
- Include return rate in product health scoring — high-return products look good on revenue but erode margin; investigate and possibly discontinue before reordering
Common Pitfalls
| Problem | Solution |
|---|---|
| Dead stock report includes recently launched products | Exclude products launched in the last 30 days from dead stock analysis; they need time to ramp up before being flagged |
| Sell-through over 100% | Inventory received was understated — check if inventory received captures all purchase orders including transfers and returns |
| Days of supply calculation shows zero for products that are not selling | Handle zero-sales denominator as "effectively infinite stock" rather than division by zero; display as "No recent sales" in reports |
| PDP conversion data does not match expectations | Verify GA4 Enhanced Ecommerce events are firing correctly on product pages; use GA4's DebugView to confirm view_item and add_to_cart events |
| Product analytics slow on large catalogs | Materialize a weekly product performance summary table in your data warehouse or use Inventory Planner's pre-computed metrics instead of querying raw order data |
Related Skills
- @sales-reporting-dashboard
- @customer-analytics
- @ab-testing-ecommerce
- @profit-margin-analysis
{
"context": "Tests whether the agent correctly implements dead stock detection using the prescribed thresholds, applies the tiered markdown recommendation logic, includes inventory value in output, excludes new arrivals, and applies category-specific thresholds for fashion vs. basics.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Days-on-hand threshold",
"max_score": 8,
"description": "Dead stock detection uses a minimum days-on-hand threshold of 90 days (not 30, 60, or other values) as the default cutoff"
},
{
"name": "Sell-through threshold",
"max_score": 8,
"description": "Dead stock filter applies a maximum sell-through threshold of 15% (0.15) or lower"
},
{
"name": "Inventory value threshold",
"max_score": 8,
"description": "Dead stock filter only flags products with inventory value (units × cost) above a minimum dollar threshold (e.g., $100), not just any product with remaining stock"
},
{
"name": "Inventory value in output",
"max_score": 10,
"description": "Each flagged product's output includes a calculated inventory value (units on hand × unit cost), not just unit count"
},
{
"name": "New arrivals excluded",
"max_score": 10,
"description": "Products available for fewer than 30 days are excluded from dead stock results (P006 with first_available_at 2026-02-20 should NOT appear in results)"
},
{
"name": "Tiered action: liquidate",
"max_score": 8,
"description": "Products with more than 180 days on hand are assigned 'liquidate' action"
},
{
"name": "Tiered action: 120-day bracket",
"max_score": 8,
"description": "Products with 120–180 days on hand are assigned 'markdown_20pct' action (not liquidate)"
},
{
"name": "Markdown percentages",
"max_score": 10,
"description": "Suggested prices use 40% discount for 'liquidate', 20% for 'markdown_20pct', and 10% for 'markdown_10pct' actions"
},
{
"name": "Category-specific thresholds",
"max_score": 12,
"description": "Fashion items use a stricter dead-stock threshold (e.g., 60 days) while basics use a more lenient threshold (e.g., 180 days), resulting in different products being flagged per category"
},
{
"name": "Human-readable reason string",
"max_score": 8,
"description": "Each recommendation includes a reason string that mentions sell-through percentage and days on hand (e.g., '18% sell-through after 163 days')"
},
{
"name": "Output structure",
"max_score": 10,
"description": "JSON output includes productId, productName, currentPrice, suggestedPrice, markdownPct, inventoryValue, daysOnHand, and reason fields for each item"
}
]
}
Seasonal Inventory Clearance Planner
Problem/Feature Description
A fashion retailer is approaching the end of the season and the buying team needs to clear slow-moving inventory before the next collection arrives. Capital tied up in unsold stock affects cash flow and warehouse space. The team wants an automated analysis that flags which products are candidates for clearance and generates specific pricing recommendations — with enough detail for the merchandising team to act on immediately.
The retailer has a mix of fashion-forward items and perennial basics, and the buying team has found that fashion pieces tend to stale out much faster than basics. They need the analysis to reflect this: more aggressive thresholds for trend items, more lenient ones for timeless basics. The output should make it clear how much money is tied up in each flagged product, not just how many units are on hand.
Output Specification
Write a self-contained TypeScript script (clearance_analysis.ts) that:
1. Processes the sample product inventory data provided below. 2. Identifies which products qualify as dead stock. 3. For each dead stock item, produces a markdown recommendation with a specific suggested price. 4. Prints a JSON report to stdout containing all flagged products and their recommendations.
The JSON report should include for each flagged product: product id, product name, current price, suggested price, markdown percentage, inventory value (units × cost), days on hand, and a short human-readable reason string.
The script must be runnable with npx ts-node clearance_analysis.ts (no database connection required — operate on the inline data below).
Input Files
The following files are provided as inputs. Extract them before beginning.
=============== FILE: inputs/products.json =============== [ { "id": "P001", "name": "Floral Wrap Dress", "sku": "FWD-001", "category": "fashion", "status": "active", "price_cents": 8900, "cost_cents": 3200, "first_available_at": "2025-09-15T00:00:00Z", "inventory_received": 120, "inventory_on_hand": 98, "units_sold": 22, "last_sale_date": "2026-01-10T00:00:00Z" }, { "id": "P002", "name": "Classic White Oxford Shirt", "sku": "CWO-002", "category": "basics", "status": "active", "price_cents": 5500, "cost_cents": 1800, "first_available_at": "2025-06-01T00:00:00Z", "inventory_received": 200, "inventory_on_hand": 60, "units_sold": 140, "last_sale_date": "2026-03-10T00:00:00Z" }, { "id": "P003", "name": "Sequin Mini Skirt", "sku": "SMS-003", "category": "fashion", "status": "active", "price_cents": 7200, "cost_cents": 2600, "first_available_at": "2025-10-01T00:00:00Z", "inventory_received": 80, "inventory_on_hand": 72, "units_sold": 8, "last_sale_date": "2025-12-20T00:00:00Z" }, { "id": "P004", "name": "Merino Wool Crewneck", "sku": "MWC-004", "category": "basics", "status": "active", "price_cents": 9500, "cost_cents": 4100, "first_available_at": "2025-08-01T00:00:00Z", "inventory_received": 150, "inventory_on_hand": 115, "units_sold": 35, "last_sale_date": "2026-02-28T00:00:00Z" }, { "id": "P005", "name": "Neon Utility Jacket", "sku": "NUJ-005", "category": "fashion", "status": "active", "price_cents": 14500, "cost_cents": 5800, "first_available_at": "2025-11-01T00:00:00Z", "inventory_received": 40, "inventory_on_hand": 38, "units_sold": 2, "last_sale_date": "2025-11-15T00:00:00Z" }, { "id": "P006", "name": "Linen Blend Trousers", "sku": "LBT-006", "category": "basics", "status": "active", "price_cents": 6800, "cost_cents": 2200, "first_available_at": "2026-02-20T00:00:00Z", "inventory_received": 90, "inventory_on_hand": 88, "units_sold": 2, "last_sale_date": "2026-03-05T00:00:00Z" }, { "id": "P007", "name": "Vintage Band Tee", "sku": "VBT-007", "category": "fashion", "status": "active", "price_cents": 3500, "cost_cents": 800, "first_available_at": "2025-07-01T00:00:00Z", "inventory_received": 300, "inventory_on_hand": 241, "units_sold": 59, "last_sale_date": "2026-01-30T00:00:00Z" } ]
{
"context": "Tests whether the agent implements the merchandising health score with the prescribed dimension weights, correct normalisation formulas for each dimension, and handles edge cases like out-of-stock products and high returns correctly.",
"type": "weighted_checklist",
"checklist": [
{
"name": "sellThrough weight",
"max_score": 7,
"description": "sellThrough dimension uses weight 0.25 in the final score calculation"
},
{
"name": "pdpConversion weight",
"max_score": 7,
"description": "pdpConversion dimension uses weight 0.25 in the final score calculation"
},
{
"name": "revenueRank weight",
"max_score": 7,
"description": "revenueRank dimension uses weight 0.20 in the final score calculation"
},
{
"name": "reviews weight",
"max_score": 7,
"description": "reviews dimension uses weight 0.15 in the final score calculation"
},
{
"name": "stockHealth weight",
"max_score": 7,
"description": "stockHealth dimension uses weight 0.10 in the final score calculation"
},
{
"name": "returns weight",
"max_score": 6,
"description": "returns dimension uses weight 0.05 in the final score calculation"
},
{
"name": "pdpConversion normalisation",
"max_score": 10,
"description": "pdpConversionPct is normalised by multiplying by 20 (so 5% CVR maps to 100), capped at 100 — A002 (pdpConversionPct=6.2) normalises to 100, not 124"
},
{
"name": "revenueRank normalisation",
"max_score": 10,
"description": "revenueRank is normalised as max(0, 100 - (rank - 1) * 2), floored at 0 — rank 1 maps to 100, rank 7 maps to 88"
},
{
"name": "reviews normalisation",
"max_score": 10,
"description": "reviewScore is normalised as ((reviewScore - 1) / 4) * 100 — a score of 1.0 maps to 0, 5.0 maps to 100"
},
{
"name": "stockHealth OOS handling",
"max_score": 10,
"description": "stockHealth is 0 when daysOnHand is 0 or negative (out of stock) — A003 (daysOnHand=-5) and A006 (daysOnHand=0) must both get stockHealth score of 0"
},
{
"name": "stockHealth cap",
"max_score": 7,
"description": "stockHealth is capped at 100 even when daysOnHand exceeds 100 — A008 (daysOnHand=110) normalises to stockHealth of 100, not 110"
},
{
"name": "returns normalisation",
"max_score": 12,
"description": "returnsRate is normalised as max(0, 100 - returnsRate * 5), floored at 0 — A006 (returnsRate=30) maps to 0 (not negative), A003 (returnsRate=22) also maps to 0"
}
]
}
Automated Collection Page Ranking
Problem/Feature Description
A fashion retailer's merchandising team currently sorts their online collection pages manually, which is time-consuming and inconsistent. They want to automate the ranking so that the best-performing products appear first. "Best-performing" means a combination of signals: how well a product sells through its inventory, how well its product page converts visitors, how strongly it contributes to revenue, how customers rate it, whether it has healthy stock levels, and whether it's generating returns that erode margins.
The team has been debating how to weight these signals. After internal discussion, they've aligned on specific weights and normalisation formulas that balance short-term revenue signals with longer-term product health indicators. They now need a developer to implement the scoring function and apply it to their current product catalog snapshot so they can validate the output before plugging it into the collection page service.
Output Specification
Write a TypeScript file (score_products.ts) that:
1. Implements a calculateMerchandisingScore function accepting a product's performance inputs. 2. Applies the scoring to the product data provided below. 3. Writes the results to ranked_products.json — a JSON array of products sorted from highest to lowest score, each entry including: productId, productName, score (rounded to 2 decimal places), and the individual normalised dimension scores.
The script must be runnable with npx ts-node score_products.ts.
Input Files
The following files are provided as inputs. Extract them before beginning.
=============== FILE: inputs/product_performance.json =============== [ { "productId": "A001", "productName": "Classic Denim Jacket", "sellThroughPct": 72, "pdpConversionPct": 3.8, "revenueRank": 3, "reviewScore": 4.6, "daysOnHand": 45, "returnsRate": 8 }, { "productId": "A002", "productName": "Oversized Graphic Tee", "sellThroughPct": 88, "pdpConversionPct": 6.2, "revenueRank": 1, "reviewScore": 4.2, "daysOnHand": 20, "returnsRate": 5 }, { "productId": "A003", "productName": "Pleated Wide-Leg Trousers", "sellThroughPct": 31, "pdpConversionPct": 1.1, "revenueRank": 18, "reviewScore": 3.8, "daysOnHand": -5, "returnsRate": 22 }, { "productId": "A004", "productName": "Linen Summer Blazer", "sellThroughPct": 55, "pdpConversionPct": 2.5, "revenueRank": 7, "reviewScore": 4.4, "daysOnHand": 90, "returnsRate": 12 }, { "productId": "A005", "productName": "Ribbed Knit Midi Dress", "sellThroughPct": 93, "pdpConversionPct": 5.0, "revenueRank": 2, "reviewScore": 4.8, "daysOnHand": 8, "returnsRate": 3 }, { "productId": "A006", "productName": "Faux Leather Biker Shorts", "sellThroughPct": 19, "pdpConversionPct": 0.7, "revenueRank": 25, "reviewScore": 3.1, "daysOnHand": 0, "returnsRate": 30 }, { "productId": "A007", "productName": "Tailored Wool Coat", "sellThroughPct": 61, "pdpConversionPct": 4.2, "revenueRank": 5, "reviewScore": 4.7, "daysOnHand": 60, "returnsRate": 6 }, { "productId": "A008", "productName": "Vintage Wash Cargo Pants", "sellThroughPct": 44, "pdpConversionPct": 1.8, "revenueRank": 12, "reviewScore": 3.9, "daysOnHand": 110, "returnsRate": 18 } ]
{
"context": "Tests whether the agent correctly implements the PDP conversion funnel SQL with proper session deduplication, minimum views threshold, correct metric formulas, and low-conversion alerting thresholds per the product analytics skill.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Session deduplication in views CTE",
"max_score": 15,
"description": "The views CTE counts DISTINCT session_id per product_id (not COUNT(*) of raw events) — this addresses the multi-variant page view inflation issue"
},
{
"name": "Three-CTE structure",
"max_score": 8,
"description": "Query uses three separate CTEs: one for views, one for add-to-cart sessions, and one for purchases — not a single monolithic join"
},
{
"name": "Minimum views filter",
"max_score": 10,
"description": "A minimum pdp_views threshold of greater than 50 is applied to exclude low-traffic products from funnel results"
},
{
"name": "Cancelled orders excluded",
"max_score": 10,
"description": "The purchases CTE or orders join filters out cancelled orders (e.g., status NOT IN ('cancelled') or equivalent)"
},
{
"name": "pdp_to_atc_pct formula",
"max_score": 10,
"description": "pdp_to_atc_pct is computed as ROUND(100.0 * atc_sessions / NULLIF(pdp_views, 0), 1) — using NULLIF to guard against division by zero"
},
{
"name": "pdp_conversion_pct formula",
"max_score": 8,
"description": "pdp_conversion_pct is computed separately as ROUND(100.0 * purchase_count / NULLIF(pdp_views, 0), 2) — a two-decimal metric distinct from ATC rate"
},
{
"name": "COALESCE for missing products",
"max_score": 8,
"description": "COALESCE is used to handle products with no ATC events or no purchases (returning 0 rather than NULL for atc_sessions and purchase_count)"
},
{
"name": "Low-conversion views threshold",
"max_score": 12,
"description": "The low-conversion alert query filters for products with more than 100 pdp_views (not just >50)"
},
{
"name": "Low-conversion ATC threshold",
"max_score": 12,
"description": "The low-conversion alert query filters for products where pdp_to_atc_pct is below 2% (not a different threshold)"
},
{
"name": "Investigation context in notes",
"max_score": 7,
"description": "analysis_notes.md mentions that low ATC rate can indicate pricing, description, or image quality issues (not just generic 'poor conversion')"
}
]
}
Product Page Conversion Audit
Problem/Feature Description
An e-commerce team has noticed that some products receive significant traffic but very few shoppers add items to their cart. The growth team suspects these are products with pricing, imagery, or copy issues — but they need data to confirm which products to prioritize for a page-quality review sprint.
The analytics team has three raw event tables in their PostgreSQL database: page_view_events (when shoppers land on a product detail page), cart_events (when shoppers click "Add to Cart"), and the orders table. Their current reporting only tracks completed orders; it ignores the full funnel, leaving them blind to where shoppers drop off. They want a set of SQL queries that computes per-product funnel metrics and surfaces a prioritized alert list of products needing attention.
There is a known data quality issue: a multi-variant product page can fire multiple page_view_events rows within the same session when the shopper browses between color/size options. The query must account for this to avoid inflated view counts.
Output Specification
Write a file called pdp_funnel.sql containing: 1. A reusable SQL query (using CTEs) that computes, for each product: total page views, add-to-cart sessions, purchase count, pdp-to-atc conversion rate, and overall pdp conversion rate. 2. A second query (or extension of the first) that produces only the products needing urgent attention due to very low add-to-cart rate.
Assume the following schema is available:
-- page_view_events: one row per page view event
-- session_id TEXT, product_id TEXT, page_type TEXT, created_at TIMESTAMPTZ
-- cart_events: one row per cart interaction
-- session_id TEXT, product_id TEXT, event TEXT ('add_to_cart'), created_at TIMESTAMPTZ
-- orders: one row per order
-- order_id TEXT, session_id TEXT, status TEXT, created_at TIMESTAMPTZ
-- order_items: one row per line item in an order
-- order_id TEXT, product_id TEXT, quantity INT
-- products: product catalog
-- id TEXT, name TEXTAlso write a brief analysis_notes.md explaining how the query handles the multi-variant page view issue and what the low-conversion alert criteria mean for the team's review process.
{
"name": "finsi/product-analytics",
"version": "0.1.0",
"summary": "Product performance metrics, sell-through rates, and dead stock identification",
"skills": {
"product-analytics": {
"path": "SKILL.md"
}
}
}