Skip to main content

Overview

The Analytics API provides comprehensive insights into marketplace performance, including product distribution, category analysis, and store metrics. These functions help administrators and stakeholders understand platform trends and make data-driven decisions. Location: convex/shared/analytics.ts

Get Product Counts by Global Category

Retrieves product counts grouped by global category across all stores in the marketplace.
const categoryStats = await convex.query(api.shared.analytics.getProductCountsByGlobalCategory);
[
  {
    "categoryId": "k123456789",
    "categoryName": "Food & Restaurants",
    "productCount": 1250
  },
  {
    "categoryId": "k987654321",
    "categoryName": "Electronics",
    "productCount": 890
  },
  {
    "categoryId": "k555666777",
    "categoryName": "Fashion & Apparel",
    "productCount": 2100
  }
]

Get Products by Global Category

Retrieves products within a specific global category with optional limit.
globalCategoryId
Id<'categories'>
required
Global category ID to filter products
limit
number
Maximum number of products to return (default: no limit)
const products = await convex.query(api.shared.analytics.getProductsByGlobalCategory, {
  globalCategoryId: "k123456789",
  limit: 50
});
[
  {
    "_id": "p123456789",
    "name": "Pizza Margherita",
    "description": "Classic Italian pizza",
    "price": 15.99,
    "storeId": "j123456789",
    "storeName": "Mario's Pizza",
    "category": {
      "id": "k123456789",
      "name": "Food & Restaurants"
    },
    "primaryImageUrl": "https://storage.convex.dev/...",
    "isActive": true,
    "_creationTime": 1640995200000
  }
]

Get Store Distribution by Global Category

Retrieves store distribution data showing how many products each store has in a specific global category.
globalCategoryId
Id<'categories'>
required
Global category ID to analyze
const storeDistribution = await convex.query(api.shared.analytics.getStoreDistributionByGlobalCategory, {
  globalCategoryId: "k123456789"
});
[
  {
    "storeId": "j123456789",
    "storeName": "Mario's Pizza",
    "productCount": 25
  },
  {
    "storeId": "j987654321",
    "storeName": "Luigi's Kitchen",
    "productCount": 18
  },
  {
    "storeId": "j555666777",
    "storeName": "Tony's Trattoria",
    "productCount": 32
  }
]

Analytics Dashboard Example

Here’s how you can build an analytics dashboard using these functions:
import { useQuery } from 'convex/react';
import { api } from './convex/_generated/api';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';

function AnalyticsDashboard() {
  const categoryStats = useQuery(api.shared.analytics.getProductCountsByGlobalCategory);

  if (!categoryStats) return <div>Loading analytics...</div>;

  return (
    <div className="p-6">
      <h2 className="text-2xl font-bold mb-6">Marketplace Analytics</h2>
      
      {/* Category Distribution Chart */}
      <div className="bg-white p-6 rounded-lg shadow mb-6">
        <h3 className="text-lg font-semibold mb-4">Products by Category</h3>
        <ResponsiveContainer width="100%" height={300}>
          <BarChart data={categoryStats}>
            <CartesianGrid strokeDasharray="3 3" />
            <XAxis dataKey="categoryName" />
            <YAxis />
            <Tooltip />
            <Bar dataKey="productCount" fill="#0D9373" />
          </BarChart>
        </ResponsiveContainer>
      </div>

      {/* Category Stats Table */}
      <div className="bg-white p-6 rounded-lg shadow">
        <h3 className="text-lg font-semibold mb-4">Category Statistics</h3>
        <div className="overflow-x-auto">
          <table className="min-w-full table-auto">
            <thead>
              <tr className="bg-gray-50">
                <th className="px-4 py-2 text-left">Category</th>
                <th className="px-4 py-2 text-right">Product Count</th>
                <th className="px-4 py-2 text-right">Percentage</th>
              </tr>
            </thead>
            <tbody>
              {categoryStats.map((category) => {
                const total = categoryStats.reduce((sum, cat) => sum + cat.productCount, 0);
                const percentage = ((category.productCount / total) * 100).toFixed(1);
                
                return (
                  <tr key={category.categoryId} className="border-t">
                    <td className="px-4 py-2">{category.categoryName}</td>
                    <td className="px-4 py-2 text-right">{category.productCount}</td>
                    <td className="px-4 py-2 text-right">{percentage}%</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

Use Cases

Platform Overview

Get high-level insights into marketplace performance and category distribution for executive dashboards.

Category Analysis

Analyze which categories are most popular and identify growth opportunities or oversaturated markets.

Store Performance

Compare store performance within categories to identify top performers and provide targeted support.

Market Research

Understand market trends and customer preferences to guide business strategy and store onboarding.

Real-time Analytics

All analytics functions return real-time data that updates automatically as the marketplace changes:
// Set up real-time analytics with React
function RealTimeAnalytics() {
  const categoryStats = useQuery(api.shared.analytics.getProductCountsByGlobalCategory);
  
  // Data automatically updates when products are added/removed
  useEffect(() => {
    if (categoryStats) {
      console.log('Analytics updated:', categoryStats);
      // Update charts, send notifications, etc.
    }
  }, [categoryStats]);
  
  return (
    <div>
      {/* Your analytics UI */}
    </div>
  );
}

Performance Considerations

Analytics queries can be expensive. Consider implementing caching:
// Cache analytics data for 5 minutes
const cachedCategoryStats = useMemo(() => {
  return categoryStats;
}, [Math.floor(Date.now() / (5 * 60 * 1000))]);
Consider updating analytics in the background:
// Update analytics every 10 minutes
useEffect(() => {
  const interval = setInterval(() => {
    // Trigger analytics refresh
    refetch();
  }, 10 * 60 * 1000);
  
  return () => clearInterval(interval);
}, []);

Error Handling

Status Code: 404
{
  "error": "Global category not found",
  "categoryId": "k123456789"
}
Status Code: 200 (Success with empty data)
[]
Status Code: 403
{
  "error": "Insufficient permissions to access analytics data"
}
Analytics data is computed in real-time and reflects the current state of the marketplace. For historical analytics, consider implementing a separate data warehouse solution.
Use the analytics functions to build comprehensive dashboards that help store owners and platform administrators make data-driven decisions.