> ## Documentation Index
> Fetch the complete documentation index at: https://twigz.arqqin.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Analytics

> Comprehensive analytics and insights for marketplace data

## 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.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const categoryStats = await convex.query(api.shared.analytics.getProductCountsByGlobalCategory);
  ```

  ```javascript JavaScript theme={null}
  const categoryStats = await convex.query("shared.analytics.getProductCountsByGlobalCategory");
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      f"{CONVEX_URL}/api/query",
      json={
          "path": "shared.analytics.getProductCountsByGlobalCategory",
          "args": {}
      },
      headers={"Authorization": f"Bearer {token}"}
  )

  category_stats = response.json()
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  [
    {
      "categoryId": "k123456789",
      "categoryName": "Food & Restaurants",
      "productCount": 1250
    },
    {
      "categoryId": "k987654321",
      "categoryName": "Electronics",
      "productCount": 890
    },
    {
      "categoryId": "k555666777",
      "categoryName": "Fashion & Apparel",
      "productCount": 2100
    }
  ]
  ```
</ResponseExample>

## Get Products by Global Category

Retrieves products within a specific global category with optional limit.

<ParamField path="globalCategoryId" type="Id<'categories'>" required>
  Global category ID to filter products
</ParamField>

<ParamField path="limit" type="number">
  Maximum number of products to return (default: no limit)
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const products = await convex.query(api.shared.analytics.getProductsByGlobalCategory, {
    globalCategoryId: "k123456789",
    limit: 50
  });
  ```

  ```javascript JavaScript theme={null}
  const products = await convex.query("shared.analytics.getProductsByGlobalCategory", {
    globalCategoryId: "k123456789",
    limit: 50
  });
  ```

  ```python Python theme={null}
  response = requests.post(
      f"{CONVEX_URL}/api/query",
      json={
          "path": "shared.analytics.getProductsByGlobalCategory",
          "args": {
              "globalCategoryId": "k123456789",
              "limit": 50
          }
      },
      headers={"Authorization": f"Bearer {token}"}
  )

  products = response.json()
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  [
    {
      "_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
    }
  ]
  ```
</ResponseExample>

## Get Store Distribution by Global Category

Retrieves store distribution data showing how many products each store has in a specific global category.

<ParamField path="globalCategoryId" type="Id<'categories'>" required>
  Global category ID to analyze
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const storeDistribution = await convex.query(api.shared.analytics.getStoreDistributionByGlobalCategory, {
    globalCategoryId: "k123456789"
  });
  ```

  ```javascript JavaScript theme={null}
  const storeDistribution = await convex.query("shared.analytics.getStoreDistributionByGlobalCategory", {
    globalCategoryId: "k123456789"
  });
  ```

  ```python Python theme={null}
  response = requests.post(
      f"{CONVEX_URL}/api/query",
      json={
          "path": "shared.analytics.getStoreDistributionByGlobalCategory",
          "args": {
              "globalCategoryId": "k123456789"
          }
      },
      headers={"Authorization": f"Bearer {token}"}
  )

  distribution = response.json()
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  [
    {
      "storeId": "j123456789",
      "storeName": "Mario's Pizza",
      "productCount": 25
    },
    {
      "storeId": "j987654321",
      "storeName": "Luigi's Kitchen",
      "productCount": 18
    },
    {
      "storeId": "j555666777",
      "storeName": "Tony's Trattoria",
      "productCount": 32
    }
  ]
  ```
</ResponseExample>

## Analytics Dashboard Example

Here's how you can build an analytics dashboard using these functions:

<CodeGroup>
  ```typescript React Dashboard theme={null}
  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>
    );
  }
  ```

  ```javascript Vue Dashboard theme={null}
  <template>
    <div class="analytics-dashboard">
      <h2>Marketplace Analytics</h2>
      
      <div v-if="loading">Loading analytics...</div>
      
      <div v-else>
        <!-- Category Stats -->
        <div class="stats-grid">
          <div v-for="category in categoryStats" :key="category.categoryId" class="stat-card">
            <h3>{{ category.categoryName }}</h3>
            <p class="stat-number">{{ category.productCount }}</p>
            <p class="stat-label">Products</p>
          </div>
        </div>
        
        <!-- Store Distribution -->
        <div class="store-distribution" v-if="selectedCategory">
          <h3>Store Distribution for {{ selectedCategoryName }}</h3>
          <div v-for="store in storeDistribution" :key="store.storeId" class="store-item">
            <span>{{ store.storeName }}</span>
            <span>{{ store.productCount }} products</span>
          </div>
        </div>
      </div>
    </div>
  </template>

  <script>
  export default {
    data() {
      return {
        categoryStats: [],
        storeDistribution: [],
        selectedCategory: null,
        loading: true
      };
    },
    
    async mounted() {
      await this.loadAnalytics();
    },
    
    methods: {
      async loadAnalytics() {
        try {
          this.categoryStats = await convex.query("shared.analytics.getProductCountsByGlobalCategory");
          this.loading = false;
        } catch (error) {
          console.error('Failed to load analytics:', error);
          this.loading = false;
        }
      },
      
      async loadStoreDistribution(categoryId) {
        this.storeDistribution = await convex.query(
          "shared.analytics.getStoreDistributionByGlobalCategory",
          { globalCategoryId: categoryId }
        );
        this.selectedCategory = categoryId;
      }
    }
  };
  </script>
  ```
</CodeGroup>

## Use Cases

<CardGroup cols={2}>
  <Card title="Platform Overview" icon="chart-line">
    Get high-level insights into marketplace performance and category distribution for executive dashboards.
  </Card>

  <Card title="Category Analysis" icon="pie-chart">
    Analyze which categories are most popular and identify growth opportunities or oversaturated markets.
  </Card>

  <Card title="Store Performance" icon="store">
    Compare store performance within categories to identify top performers and provide targeted support.
  </Card>

  <Card title="Market Research" icon="magnifying-glass-chart">
    Understand market trends and customer preferences to guide business strategy and store onboarding.
  </Card>
</CardGroup>

## Real-time Analytics

All analytics functions return real-time data that updates automatically as the marketplace changes:

```typescript theme={null}
// 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

<AccordionGroup>
  <Accordion title="Caching Strategy">
    Analytics queries can be expensive. Consider implementing caching:

    ```typescript theme={null}
    // Cache analytics data for 5 minutes
    const cachedCategoryStats = useMemo(() => {
      return categoryStats;
    }, [Math.floor(Date.now() / (5 * 60 * 1000))]);
    ```
  </Accordion>

  <Accordion title="Pagination">
    For large datasets, use the limit parameter:

    ```typescript theme={null}
    // Get top 20 products in category
    const topProducts = await convex.query(api.shared.analytics.getProductsByGlobalCategory, {
      globalCategoryId: "k123456789",
      limit: 20
    });
    ```
  </Accordion>

  <Accordion title="Background Updates">
    Consider updating analytics in the background:

    ```typescript theme={null}
    // Update analytics every 10 minutes
    useEffect(() => {
      const interval = setInterval(() => {
        // Trigger analytics refresh
        refetch();
      }, 10 * 60 * 1000);
      
      return () => clearInterval(interval);
    }, []);
    ```
  </Accordion>
</AccordionGroup>

## Error Handling

<AccordionGroup>
  <Accordion title="Category not found">
    **Status Code**: `404`

    ```json theme={null}
    {
      "error": "Global category not found",
      "categoryId": "k123456789"
    }
    ```
  </Accordion>

  <Accordion title="No data available">
    **Status Code**: `200` (Success with empty data)

    ```json theme={null}
    []
    ```
  </Accordion>

  <Accordion title="Access denied">
    **Status Code**: `403`

    ```json theme={null}
    {
      "error": "Insufficient permissions to access analytics data"
    }
    ```
  </Accordion>
</AccordionGroup>

<Note>
  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.
</Note>

<Tip>
  Use the analytics functions to build comprehensive dashboards that help store owners and platform administrators make data-driven decisions.
</Tip>
