Skip to main content

Admin Analytics API

The Admin Analytics API provides comprehensive gallery-wide metrics for platform administrators. View sales data, artist performance, cart metrics, and referral conversions.

Authentication

Requires Supabase authentication with admin role:

Authorization: Bearer <access_token>

Endpoint

Retrieves comprehensive gallery-wide analytics.

Endpoint: GET /api/admin/analytics

Authentication: Required (admin only)

Query Parameters:

ParameterTypeDescription
start_datestringStart date (ISO 8601, default: 30 days ago)
end_datestringEnd date (ISO 8601, default: now)

Response:

{
"analytics": {
"overview": {
"totalOrders": 156,
"totalRevenue": 18750.00,
"galleryRevenue": 2250.00,
"artistPayouts": 16500.00,
"averageOrderValue": 120.19,
"totalItemsSold": 284
},
"ordersByStatus": {
"pending": 2,
"paid": 8,
"processing": 12,
"partially_shipped": 15,
"shipped": 89,
"delivered": 30
},
"topArtists": [
{
"orgId": "org_abc",
"artistName": "Jane Smith Studio",
"totalOrders": 42,
"totalRevenue": 5250.00,
"artistPayout": 4620.00,
"itemsSold": 78
},
{
"orgId": "org_def",
"artistName": "Bob's Pottery",
"totalOrders": 38,
"totalRevenue": 3800.00,
"artistPayout": 3344.00,
"itemsSold": 56
}
],
"cartMetrics": {
"activeCarts": 45,
"averageCartValue": 225.50,
"abandonmentRate": 32.5,
"averageItemsPerCart": 3.2
},
"referralMetrics": {
"totalReferrals": 342,
"conversions": 68,
"conversionRate": 19.88,
"attributedRevenue": 6840.00
},
"timeline": [
{
"date": "2024-01-01",
"orders": 8,
"revenue": 960.00,
"newCarts": 24
},
{
"date": "2024-01-02",
"orders": 12,
"revenue": 1440.00,
"newCarts": 31
}
],
"dateRange": {
"start": "2024-01-01T00:00:00Z",
"end": "2024-01-31T23:59:59Z"
}
}
}

Response Fields:

Overview

FieldTypeDescription
totalOrdersnumberTotal gallery orders placed
totalRevenuenumberTotal product revenue (before commission)
galleryRevenuenumber12% gallery commission earned
artistPayoutsnumber88% paid out to artists
averageOrderValuenumberAverage revenue per order
totalItemsSoldnumberTotal quantity of items sold

Orders by Status

Count of orders in each status:

  • pending: Payment not completed
  • paid: Awaiting fulfillment
  • processing: Artists preparing items
  • partially_shipped: Some artists shipped
  • shipped: All artists shipped
  • delivered: All items delivered

Top Artists

Top 10 artists by revenue:

FieldTypeDescription
orgIdstringArtist organization ID
artistNamestringArtist display name
totalOrdersnumberOrders containing their products
totalRevenuenumberTotal product revenue
artistPayoutnumberAmount paid to artist
itemsSoldnumberQuantity of items sold

Cart Metrics

FieldTypeDescription
activeCartsnumberNon-empty carts in last 30 days
averageCartValuenumberAverage value of active carts
abandonmentRatenumber% of carts not converted to orders
averageItemsPerCartnumberAverage quantity per cart

Referral Metrics

FieldTypeDescription
totalReferralsnumberGallery → artist store clicks
conversionsnumberReferrals who purchased within 30 days
conversionRatenumberConversion percentage
attributedRevenuenumberRevenue from attributed conversions

Note: Attributed revenue is from individual artist stores (not gallery sales). Artists keep 100% minus Stripe fees on attributed sales.

Timeline

Daily breakdown of activity:

FieldTypeDescription
datestringDate (YYYY-MM-DD)
ordersnumberOrders placed
revenuenumberRevenue generated
newCartsnumberNew cart sessions created

Example Request:

curl "https://gallery.artbase.studio/api/admin/analytics" \
-H "Authorization: Bearer <admin_token>"

Example with Date Range:

curl "https://gallery.artbase.studio/api/admin/analytics?start_date=2024-01-01&end_date=2024-01-31" \
-H "Authorization: Bearer <admin_token>"

Error Responses:

StatusErrorDescription
401UnauthorizedNot logged in
403ForbiddenNot an admin

Key Metrics Explained

Gallery uses a transparent 88/12 split:

Product Price: $100
├─ Artist Payout (88%): $88
└─ Gallery Commission (12%): $12

Customer Pays: ~$115 (includes Stripe fees)

Gallery Revenue = 12% of all product sales Artist Payouts = 88% of all product sales

Cart Abandonment Rate

Abandonment Rate = (Carts - Orders) / Carts × 100

Example:

  • 100 active carts
  • 65 orders completed
  • Abandonment rate = (100 - 65) / 100 = 35%

Industry benchmarks:

  • ✅ Below 30%: Excellent
  • 👍 30-50%: Good
  • ⚠️ 50-70%: Needs improvement
  • ❌ Above 70%: Critical issue

Referral Conversion Rate

Conversion Rate = Conversions / Total Referrals × 100

Measures how well the gallery drives sales to individual artist stores.

Benchmarks:

  • ✅ Above 20%: Excellent
  • 👍 10-20%: Good
  • ⚠️ 5-10%: Fair
  • ❌ Below 5%: Poor

Use Cases

Admin Dashboard

Display key metrics:

import { useEffect, useState } from 'react';

export function AdminDashboard({ token }) {
const [analytics, setAnalytics] = useState(null);

useEffect(() => {
async function fetchAnalytics() {
const res = await fetch('/api/admin/analytics', {
headers: { Authorization: `Bearer ${token}` },
});
const data = await res.json();
setAnalytics(data.analytics);
}
fetchAnalytics();
}, [token]);

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

const { overview, ordersByStatus, topArtists, cartMetrics } = analytics;

return (
<div>
<h1>Gallery Analytics</h1>

<div className="metrics-grid">
<div className="metric">
<h3>Total Revenue</h3>
<p>${overview.totalRevenue.toFixed(2)}</p>
</div>
<div className="metric">
<h3>Gallery Commission</h3>
<p>${overview.galleryRevenue.toFixed(2)}</p>
</div>
<div className="metric">
<h3>Total Orders</h3>
<p>{overview.totalOrders}</p>
</div>
<div className="metric">
<h3>Avg Order Value</h3>
<p>${overview.averageOrderValue.toFixed(2)}</p>
</div>
</div>

<h2>Top Artists</h2>
<table>
<thead>
<tr>
<th>Artist</th>
<th>Orders</th>
<th>Revenue</th>
<th>Items Sold</th>
</tr>
</thead>
<tbody>
{topArtists.map(artist => (
<tr key={artist.orgId}>
<td>{artist.artistName}</td>
<td>{artist.totalOrders}</td>
<td>${artist.totalRevenue.toFixed(2)}</td>
<td>{artist.itemsSold}</td>
</tr>
))}
</tbody>
</table>

<h2>Cart Metrics</h2>
<p>Active carts: {cartMetrics.activeCarts}</p>
<p>Abandonment rate: {cartMetrics.abandonmentRate.toFixed(1)}%</p>
</div>
);
}

Revenue Chart

Visualize daily revenue:

import { Line } from 'react-chartjs-2';

export function RevenueChart({ timeline }) {
const data = {
labels: timeline.map(day => day.date),
datasets: [
{
label: 'Daily Revenue',
data: timeline.map(day => day.revenue),
borderColor: 'rgb(75, 192, 192)',
tension: 0.1,
},
{
label: 'Daily Orders',
data: timeline.map(day => day.orders),
borderColor: 'rgb(255, 99, 132)',
tension: 0.1,
},
],
};

return <Line data={data} />;
}

Export Analytics Report

async function exportAnalytics(token: string, startDate: string, endDate: string) {
const res = await fetch(
`/api/admin/analytics?start_date=${startDate}&end_date=${endDate}`,
{
headers: { Authorization: `Bearer ${token}` },
}
);
const { analytics } = await res.json();

const csv = [
['Gallery Analytics Report'],
[`Date Range: ${startDate} to ${endDate}`],
[''],
['Overview'],
['Total Orders', analytics.overview.totalOrders],
['Total Revenue', analytics.overview.totalRevenue],
['Gallery Revenue', analytics.overview.galleryRevenue],
['Artist Payouts', analytics.overview.artistPayouts],
['Average Order Value', analytics.overview.averageOrderValue],
[''],
['Top Artists'],
['Artist', 'Orders', 'Revenue', 'Payout'],
...analytics.topArtists.map(a => [
a.artistName,
a.totalOrders,
a.totalRevenue,
a.artistPayout,
]),
]
.map(row => row.join(','))
.join('\n');

const blob = new Blob([csv], { type: 'text/csv' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `gallery-analytics-${startDate}-${endDate}.csv`;
a.click();
}

Performance Optimization

Reduce Cart Abandonment

If abandonment rate is high (>50%):

  1. Simplify checkout - Reduce steps, fewer form fields
  2. Show trust signals - Security badges, return policy
  3. Email reminders - Send abandoned cart emails
  4. Shipping transparency - Clear shipping costs and timelines
  5. Guest checkout - Don't require account creation

Improve Referral Conversions

If conversion rate is low (<10%):

  1. Better CTAs - "Visit Artist Store" more prominent
  2. Artist profiles - Richer artist pages on gallery
  3. Incentives - First-time buyer discounts on artist stores
  4. Email follow-up - "Liked this artist? Visit their store"
  5. Retargeting - Pixel-based remarketing

Boost Average Order Value

Increase AOV with:

  1. Bundles - "Complete the collection" suggestions
  2. Free shipping threshold - "Add $X for free shipping"
  3. Cross-sells - "Customers also bought..."
  4. Volume discounts - "Buy 2, save 10%"

Next Steps