Chapter 19: Dashboard & Analytics
Dashboard Overview
The dashboard is the first screen merchants see after opening AdPriority. Its purpose is to answer three questions in under five seconds: How are my products distributed across priority levels? Is everything syncing correctly? Is there anything that needs my attention?
The dashboard is intentionally not a deep analytics tool. For the Starter and Growth tiers, it provides operational awareness. The Pro tier adds performance analytics powered by Google Ads data.
Priority Distribution Chart
The centerpiece of the dashboard is a pie chart (or doughnut chart) showing how many products fall into each priority level. This gives the merchant an instant visual sense of their catalog’s advertising posture.
PRIORITY DISTRIBUTION (Nexus Clothing - Winter)
================================================
+-------+
/ 5 \ 5 - Push Hard: 312 (13%)
/ (312) \ 4 - Strong: 487 (20%)
| +-------+ | 3 - Normal: 824 (34%)
| | | | 2 - Low: 401 (17%)
| 4 | PIE | 3 | 1 - Minimal: 198 (8%)
| | CHART | | 0 - Exclude: 203 (8%)
|(487) |(824) | --------------------------
\ +-------+ / Total Active: 2,425
\ 2 (401) /
+--1--+
(198)
0 (203)
Color Key:
[green] 5 [teal] 4 [yellow] 3 [orange] 2 [red] 1 [grey] 0
Chart Implementation
The chart uses Chart.js with the following configuration:
const distributionData = {
labels: [
"5 - Push Hard",
"4 - Strong",
"3 - Normal",
"2 - Low",
"1 - Minimal",
"0 - Exclude",
],
datasets: [{
data: [312, 487, 824, 401, 198, 203],
backgroundColor: [
"#008060", // Polaris success (green)
"#2B6CB0", // Polaris info (teal)
"#B98900", // Polaris attention (yellow)
"#C05717", // Polaris warning (orange)
"#D72C0D", // Polaris critical (red)
"#8C9196", // Polaris subdued (grey)
],
}],
};
The chart renders inside a Polaris Card with the heading “Priority Distribution”. Below the chart, a summary table lists each level with the count and percentage. Clicking a segment navigates to the Products screen pre-filtered to that priority level.
Distribution Alerts
The dashboard monitors the distribution for anomalies and surfaces them as Polaris Banner components:
| Condition | Banner Tone | Message |
|---|---|---|
| More than 30% of active products at priority 0 | warning | “312 active products are excluded from ads. Review your rules to ensure this is intentional.” |
| Zero products at priority 5 | info | “No products are set to maximum priority. Consider boosting seasonal bestsellers.” |
| All products at the same priority | warning | “All products share the same priority. Differentiation is needed for PMAX to allocate budget effectively.” |
| Distribution unchanged for 30+ days | info | “Your priority distribution has not changed in over 30 days. Review seasonal settings.” |
Sync Status
The sync status card shows the health of the three integration points: Shopify product data, Google Sheets feed, and Google Merchant Center pickup.
SYNC STATUS CARD
================
+-----------------------------------------------+
| Sync Status |
| |
| Shopify Products |
| Last sync: 2 minutes ago [green] |
| Products imported: 2,425 |
| Status: Up to date |
| |
| Google Sheet |
| Last write: 1 hour ago [green] |
| Rows written: 15,284 variants |
| Status: Synced |
| |
| Google Merchant Center |
| Feed schedule: Daily at 2:00 AM [green] |
| Last fetch: Today at 2:03 AM |
| Matched: 15,284 / 15,284 (100%) |
| Status: All labels applied |
| |
| Next scheduled sync: Today at 3:00 PM |
| [Sync Now]|
+-----------------------------------------------+
Status Indicators
Each integration point displays a colored indicator:
| Status | Indicator | Condition |
|---|---|---|
| Healthy | Green circle | Last sync completed within expected interval, zero errors |
| Stale | Yellow circle | Last sync exceeds expected interval by 2x or more |
| Error | Red circle | Last sync failed, or error rate exceeds 5% |
| Pending | Grey circle | Sync in progress or never synced |
Sync Timeline
Below the status indicators, a collapsible timeline shows the last 10 sync events in reverse chronological order:
SYNC TIMELINE (last 10 events)
===============================
[green] Today 10:30 AM - Shopify sync completed (2,425 products, 0 errors)
[green] Today 10:28 AM - Sheet updated (15,284 rows written)
[green] Today 02:03 AM - GMC fetched feed (15,284 matched)
[green] Yesterday 4:00 PM - Shopify sync completed (2,425 products, 0 errors)
[green] Yesterday 3:58 PM - Sheet updated (15,284 rows written)
[yellow] Yesterday 2:00 AM - GMC fetched feed (15,281 matched, 3 unmatched)
[green] Feb 8, 10:00 AM - Shopify sync completed (2,423 products, 0 errors)
...
Each event is stored in the sync_logs table and retrieved via the /api/sync/logs endpoint with pagination.
Quick Stats
The quick stats card provides key numbers at a glance. Each number is a Polaris Text component with variant="headingXl" and a descriptive sublabel.
QUICK STATS CARD
================
+-------------------+-------------------+
| 2,425 | 15,284 |
| Active Products | Variants in GMC |
+-------------------+-------------------+
| 47 | 12 |
| Needs Attention | New Arrivals |
+-------------------+-------------------+
| 20 | 4 |
| Rules Active | Seasons Defined |
+-------------------+-------------------+
Metric Definitions
| Metric | Definition | Data Source |
|---|---|---|
| Active Products | Products with status = 'active' in Shopify | products table count where shopify_status = 'active' |
| Variants in GMC | Total variant rows written to the supplemental feed | products table count where sync_status = 'synced' |
| Needs Attention | Products with priority 0 that have inventory > 0 and are not tagged archived or DEAD50 | Query: priority = 0 AND inventory_quantity > 0 AND 'archived' NOT IN tags AND 'DEAD50' NOT IN tags |
| New Arrivals | Products created within the configured new arrival window (default 14 days) | Query: created_at > NOW() - INTERVAL '14 days' |
| Rules Active | Number of enabled rules | rules table count where is_active = true |
| Seasons Defined | Number of configured seasons | seasons table count |
Needs Attention Detail
The “Needs Attention” count is the most actionable metric on the dashboard. Clicking it navigates to the Products screen filtered to show these products. These are products that:
- Are active in Shopify (not archived, not draft)
- Have inventory available (could be sold)
- Currently have priority 0 (excluded from all advertising)
- Are NOT intentionally excluded (no
archivedorDEAD50tag)
This typically catches products that fell to priority 0 due to an overly aggressive rule or a missing category mapping. The merchant can review them and either adjust rules or manually override.
Seasonal Recommendations
When a season transition is approaching (within 14 days), a Banner appears on the dashboard:
+------------------------------------------------------------------+
| [info] Season transition approaching |
| |
| Spring begins on March 1 (19 days away). When the transition |
| occurs, 847 products will change priority: |
| - 312 products will increase (Shorts 0->3, T-Shirts 2->4) |
| - 535 products will decrease (Outerwear 5->1, Beanies 5->1) |
| |
| [Preview Changes] [Dismiss] |
+------------------------------------------------------------------+
The “Preview Changes” button navigates to a temporary comparison view showing the before and after priority for every affected product, grouped by category.
Activity Feed
The activity feed is a chronological log of significant events, displayed as a Polaris ResourceList inside a Card.
ACTIVITY FEED
=============
+-----------------------------------------------+
| Recent Activity [View All] |
| |
| Today |
| |
| 10:32 AM Priority changed |
| 47 products updated by seasonal |
| rules (Winter applied) |
| |
| 10:30 AM Sync completed |
| 2,425 products synced to Google |
| Sheet (0 errors) |
| |
| 09:15 AM Manual override |
| "Jordan Craig Stacked Jeans" set to |
| priority 5 by merchant |
| Reason: "Holiday promo" |
| |
| Yesterday |
| |
| 04:00 PM Rule created |
| "Outerwear - Heavy" rule added |
| (matches 35 products) |
| |
| 02:03 AM GMC feed processed |
| 15,284 variants matched (100%) |
| |
+-----------------------------------------------+
Event Types
| Event Type | Icon | Description |
|---|---|---|
sync_completed | Checkmark | Shopify or Sheet sync finished |
sync_failed | Alert | Sync encountered errors |
priority_changed | Arrow | Products changed priority (bulk or individual) |
rule_created | Plus | New rule added |
rule_updated | Edit | Rule modified |
season_transition | Calendar | Active season changed |
manual_override | Lock | Merchant manually set a priority |
gmc_feed_processed | Cloud | GMC fetched the supplemental feed |
Events are sourced from two tables: audit_logs for priority and rule changes, and sync_logs for sync events. The feed shows the 20 most recent events with a “View All” link to a full activity log page.
Pro Tier Analytics
Merchants on the Pro tier ($199/mo) unlock a performance analytics section powered by Google Ads data. This section appears below the standard dashboard cards and is hidden for Starter and Growth tier subscribers.
ROAS by Priority Tier
The primary Pro analytics view shows Return on Ad Spend broken down by priority level. This directly answers the question: “Is higher priority actually producing better returns?”
ROAS BY PRIORITY TIER (Last 30 Days)
=====================================
Priority Spend Revenue ROAS Conversions
-------- -------- --------- ------ -----------
5 - Push $3,240 $16,200 5.0x 324
4 - Strong $2,810 $11,240 4.0x 281
3 - Normal $1,950 $5,850 3.0x 195
2 - Low $480 $1,200 2.5x 48
1 - Minimal $120 $240 2.0x 12
0 - Exclude $0 $0 -- 0
-------- -------- --------- ------ -----------
TOTAL $8,600 $34,730 4.0x 860
[BAR CHART: ROAS by priority level]
5 |====================| 5.0x
4 |================| 4.0x
3 |============| 3.0x
2 |==========| 2.5x
1 |========| 2.0x
0 | --
+------+------+------+------+
0x 2x 4x 6x
Google Ads Performance
A time-series chart shows aggregate performance trends over the selected period (7 days, 30 days, 90 days):
PERFORMANCE TREND (30 Days)
============================
ROAS
6x | *
5x | * * * * * *
4x | * * * * * *
3x | * *
2x |
1x |
+--+--+--+--+--+--+--+--+--+-->
W1 W2 W3 W4 Today
--- Spend --- Revenue --- ROAS
Budget Recommendations
Based on the performance data, AdPriority generates actionable recommendations:
BUDGET RECOMMENDATIONS
======================
+-----------------------------------------------+
| [info] Recommendation: Increase Priority 5 |
| budget |
| |
| Priority 5 products have 5.0x ROAS, the |
| highest in your catalog. Consider increasing |
| the PMAX budget for this tier by 20%. |
| |
| Estimated impact: +$650 revenue/week |
| |
| [Apply Suggestion] [Dismiss] |
+-----------------------------------------------+
| |
| [warning] Low performers detected |
| |
| 23 products in Priority 3 have ROAS below 1.5x.|
| Consider moving them to Priority 2 to reduce |
| wasted spend. |
| |
| [View Products] [Dismiss] |
+-----------------------------------------------+
Recommendations are generated by the backend analytics service, which runs nightly after pulling the latest Google Ads performance data. Each recommendation includes:
| Field | Description |
|---|---|
| Type | increase_budget, decrease_budget, reprioritize, exclude |
| Confidence | High, Medium, Low (based on data volume and statistical significance) |
| Estimated impact | Projected revenue change based on historical trends |
| Affected products | Count and list of products the recommendation applies to |
| Action | One-click apply button that adjusts priorities accordingly |
Data Sources for Pro Analytics
| Data Point | Source | Frequency |
|---|---|---|
| Spend by product group | Google Ads API SearchStream | Daily |
| Revenue by product group | Google Ads API conversion tracking | Daily |
| Impressions and clicks | Google Ads API campaign metrics | Daily |
| ROAS calculation | revenue / spend computed in backend | On demand |
| Product-level attribution | Google Ads shopping_performance_view | Daily |
The Google Ads API requires separate OAuth consent. Merchants connect their Google Ads account in Settings, granting read-only access to campaign performance data. AdPriority never modifies Google Ads campaigns directly; it only reads performance data and adjusts custom labels in GMC.
Dashboard Data Loading
The dashboard fetches data from four API endpoints in parallel on mount:
DASHBOARD DATA LOADING
======================
Page Mount
|
+---> GET /api/dashboard/distribution --> Priority pie chart
|
+---> GET /api/dashboard/sync-status --> Sync health indicators
|
+---> GET /api/dashboard/stats --> Quick stats numbers
|
+---> GET /api/dashboard/activity --> Recent activity feed
|
+---> GET /api/dashboard/analytics --> Pro tier only (if authorized)
|
v
All responses cached by React Query (stale time: 30 seconds)
Auto-refetch on window focus
Each endpoint is lightweight, returning pre-aggregated data from materialized counts rather than computing them on every request. The sync-status endpoint polls every 30 seconds to keep the sync indicators current.
Loading and Error States
| State | Behavior |
|---|---|
| Initial load | Polaris SkeletonPage with SkeletonBodyText placeholders |
| Partial failure | Show available data, display Banner with tone="critical" for failed sections |
| Full failure | EmptyState with error message and “Retry” button |
| No products | EmptyState with illustration and “Import Products” call to action |
| Stale data | Show cached data with subtle “Refreshing…” indicator, no blocking spinner |