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:

ConditionBanner ToneMessage
More than 30% of active products at priority 0warning“312 active products are excluded from ads. Review your rules to ensure this is intentional.”
Zero products at priority 5info“No products are set to maximum priority. Consider boosting seasonal bestsellers.”
All products at the same prioritywarning“All products share the same priority. Differentiation is needed for PMAX to allocate budget effectively.”
Distribution unchanged for 30+ daysinfo“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:

StatusIndicatorCondition
HealthyGreen circleLast sync completed within expected interval, zero errors
StaleYellow circleLast sync exceeds expected interval by 2x or more
ErrorRed circleLast sync failed, or error rate exceeds 5%
PendingGrey circleSync 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

MetricDefinitionData Source
Active ProductsProducts with status = 'active' in Shopifyproducts table count where shopify_status = 'active'
Variants in GMCTotal variant rows written to the supplemental feedproducts table count where sync_status = 'synced'
Needs AttentionProducts with priority 0 that have inventory > 0 and are not tagged archived or DEAD50Query: priority = 0 AND inventory_quantity > 0 AND 'archived' NOT IN tags AND 'DEAD50' NOT IN tags
New ArrivalsProducts created within the configured new arrival window (default 14 days)Query: created_at > NOW() - INTERVAL '14 days'
Rules ActiveNumber of enabled rulesrules table count where is_active = true
Seasons DefinedNumber of configured seasonsseasons 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:

  1. Are active in Shopify (not archived, not draft)
  2. Have inventory available (could be sold)
  3. Currently have priority 0 (excluded from all advertising)
  4. Are NOT intentionally excluded (no archived or DEAD50 tag)

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 TypeIconDescription
sync_completedCheckmarkShopify or Sheet sync finished
sync_failedAlertSync encountered errors
priority_changedArrowProducts changed priority (bulk or individual)
rule_createdPlusNew rule added
rule_updatedEditRule modified
season_transitionCalendarActive season changed
manual_overrideLockMerchant manually set a priority
gmc_feed_processedCloudGMC 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

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:

FieldDescription
Typeincrease_budget, decrease_budget, reprioritize, exclude
ConfidenceHigh, Medium, Low (based on data volume and statistical significance)
Estimated impactProjected revenue change based on historical trends
Affected productsCount and list of products the recommendation applies to
ActionOne-click apply button that adjusts priorities accordingly

Data Sources for Pro Analytics

Data PointSourceFrequency
Spend by product groupGoogle Ads API SearchStreamDaily
Revenue by product groupGoogle Ads API conversion trackingDaily
Impressions and clicksGoogle Ads API campaign metricsDaily
ROAS calculationrevenue / spend computed in backendOn demand
Product-level attributionGoogle Ads shopping_performance_viewDaily

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

StateBehavior
Initial loadPolaris SkeletonPage with SkeletonBodyText placeholders
Partial failureShow available data, display Banner with tone="critical" for failed sections
Full failureEmptyState with error message and “Retry” button
No productsEmptyState with illustration and “Import Products” call to action
Stale dataShow cached data with subtle “Refreshing…” indicator, no blocking spinner