Skip to content

Tag Analytics

Tag analytics provides aggregate metric views across product tags — enabling Creative and Ops teams to understand which design categories, themes, and product lines are performing. It builds on the tag classification system and the mart refresh pipeline.

Goal: Answer questions like “How are all iPhone-floral products performing?” or “Which tag category has the highest 30-day sales?”

MethodPathSpecDescription
GET/analytics/commerce/productsanalytics.yamlProduct performance ranked by revenue/units
GET/analytics/commerce/overviewanalytics.yamlCommerce headline KPIs for date range
MethodPathDescription
POST/api/tag-analytics/performanceAggregated metrics for a set of tags
GET/api/tag-analytics/distribution/:categoryTag distribution within a category
GET/api/tag-analytics/group-performance/:groupIdMetrics for a saved tag group
POST/api/tag-analytics/refreshTrigger refresh of the tag performance aggregate
MethodPathSpecDescription
GET/tagsproduct.yamlList product tags (flat labels)
GET/categoriesproduct.yamlList product categories
TableModuleRole
productProductRead: product catalog for join
product_tagProductRead: tag-to-product links
measurement.sales (R2 Iceberg)AnalyticsRead: sales metrics per product
product_categoryProductRead: tag group storage (rewrite target)
ResourceTypePurpose
dashboard-apiCF Worker (internal)Analytics query endpoints
measurement.salesR2 Iceberg tableSales metric source
PlanetScale (Hyperdrive)Managed PostgresProduct + tag + category data
Mart refresh jobCF Cron TriggerRebuilds performance aggregates
ActorRole
Staff user (Creative/Ops)Explores tag metrics, creates tag groups, refreshes views
Dashboard API WorkerServes analytics endpoints
PlanetScaleStore for tag/product data
Mart refresh jobRebuilds performance aggregates
// POST /api/tag-analytics/performance
{
tagNames: string[] // Tag identifiers, e.g. ["floral", "iphone-15", "summer-2024"]
}

Returns aggregated metrics (total units, 30-day units, product counts) for the given set of tags.

The distribution endpoint returns how tags within a category are distributed across products — useful for understanding coverage (e.g., “80% of products have a season tag, but only 30% have a designer tag”).

sequenceDiagram
    participant User as Staff user
    participant API as Dashboard API
    participant DB as PlanetScale

    User->>API: POST /tag-analytics/performance
    API->>DB: Query product + measurement.sales (R2) + product_tag
    DB-->>API: Aggregated metrics
    API-->>User: Tag performance metrics

    User->>API: POST /tag-analytics/refresh
    API->>DB: Rebuild tag performance aggregate
    DB-->>API: Success
    API-->>User: { success: true }

The current system relies on Supabase RPC functions for all tag analytics:

Current RPCTarget implementation
get_tag_performance_aggregate(tagNames)TypeScript query joining product + measurement.sales (R2) + product_tag, filtered by tag names
get_tag_distribution_by_category(category)TypeScript query counting products per tag within a category
get_tag_group_performance(groupId)Lookup tag group -> get tag names -> run aggregate query
refresh_tag_performance_aggregate()Background job rebuilds aggregate table (runs hourly via cron)
  • Performance aggregate returns correct metric totals for a given set of tags
  • Distribution endpoint shows accurate product counts per tag within a category
  • Tag group performance matches manually querying the group’s constituent tags
  • Refresh endpoint triggers a rebuild and the metrics reflect within the next query