Skip to main content

Artist Analytics API

The Artist Analytics API provides performance metrics for artists selling in the gallery. Track sales, revenue, top products, and referral conversions.

Authentication

Requires Supabase authentication with artist organization membership:

Authorization: Bearer <access_token>

Endpoints

Get Artist Analytics

Retrieves comprehensive analytics for an artist's gallery performance.

Endpoint: GET /api/gallery/artist/analytics

Authentication: Required (Supabase JWT)

Query Parameters:

ParameterTypeRequiredDescription
org_idstringYesArtist's organization UUID
start_datestringNoStart date (ISO 8601, default: 30 days ago)
end_datestringNoEnd date (ISO 8601, default: now)

Response:

{
"analytics": {
"overview": {
"totalOrders": 24,
"totalRevenue": 2850.00,
"galleryCommission": 342.00,
"artistPayout": 2508.00,
"averageOrderValue": 118.75,
"totalItemsSold": 42
},
"ordersByStatus": {
"paid": 3,
"processing": 2,
"shipped": 12,
"delivered": 7
},
"topProducts": [
{
"productId": "prod_001",
"productName": "Abstract Painting #5",
"totalRevenue": 900.00,
"unitsSold": 6,
"averagePrice": 150.00
},
{
"productId": "prod_002",
"productName": "Ceramic Vase",
"totalRevenue": 640.00,
"unitsSold": 8,
"averagePrice": 80.00
}
],
"referrals": {
"totalReferrals": 42,
"conversions": 8,
"conversionRate": 19.05,
"attributedRevenue": 680.00
},
"timeline": [
{
"date": "2024-01-01",
"orders": 3,
"revenue": 425.00
},
{
"date": "2024-01-02",
"orders": 5,
"revenue": 680.00
}
],
"dateRange": {
"start": "2024-01-01T00:00:00Z",
"end": "2024-01-31T23:59:59Z"
}
}
}

Response Fields:

Overview

FieldTypeDescription
totalOrdersnumberNumber of orders containing artist's items
totalRevenuenumberTotal product revenue (before commission)
galleryCommissionnumber12% gallery commission
artistPayoutnumber88% payout to artist
averageOrderValuenumberAverage revenue per order
totalItemsSoldnumberTotal quantity of items sold

Orders by Status

StatusDescription
paidPayment received, awaiting fulfillment
processingArtist is preparing items
shippedArtist has shipped items
deliveredItems delivered to customer

Top Products

FieldTypeDescription
productIdstringProduct UUID
productNamestringProduct name
totalRevenuenumberRevenue from this product
unitsSoldnumberQuantity sold
averagePricenumberAverage price per unit

Referrals

FieldTypeDescription
totalReferralsnumberGallery visitors who clicked through to artist store
conversionsnumberReferrals who purchased within 30 days
conversionRatenumberConversion percentage
attributedRevenuenumberRevenue from attributed conversions

Note: Attributed revenue is from artist's individual store, not gallery sales. Artist keeps 100% (minus Stripe fees) on attributed sales.

Timeline

Daily breakdown of orders and revenue within the date range:

FieldTypeDescription
datestringDate (YYYY-MM-DD)
ordersnumberOrders on this date
revenuenumberRevenue on this date

Example Request:

curl "https://gallery.artbase.studio/api/gallery/artist/analytics?org_id=org_abc123" \
-H "Authorization: Bearer <token>"

Example with Date Range:

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

Error Responses:

StatusErrorDescription
400Organization ID requiredMissing org_id parameter
401UnauthorizedMissing or invalid token
403ForbiddenUser not member of organization

Understanding the Metrics

Revenue Calculation

// Per-order calculation
const productRevenue = orderItems.reduce(
(sum, item) => sum + (item.price * item.quantity),
0
);
const galleryCommission = productRevenue * 0.12;
const artistPayout = productRevenue * 0.88;

// Artist receives payout via Stripe Transfer
// Gallery commission + Stripe fees paid by customer

Example: $100 product

ComponentAmount
Product revenue$100.00
Gallery commission (12%)$12.00
Artist payout (88%)$88.00

Customer pays: ~$115 (includes Stripe fees)

Referral Attribution

Referral tracking works as follows:

  1. User visits gallery - Views artist's work on gallery.artbase.studio
  2. Clicks through - Visits artist's individual store (artist.artbase.studio)
  3. Cookie set - 30-day attribution cookie stored
  4. Purchase within 30 days - Tracked as conversion
  5. Artist keeps 100% - No gallery commission on attributed sales

Benefits for Artists:

  • Use gallery as marketing/discovery channel
  • Keep full revenue on direct sales
  • Build direct customer relationships

Top Products Algorithm

Products ranked by total revenue:

const topProducts = products
.map(product => ({
...product,
totalRevenue: product.orders.reduce(
(sum, order) => sum + (order.price * order.quantity),
0
),
unitsSold: product.orders.reduce(
(sum, order) => sum + order.quantity,
0
),
}))
.sort((a, b) => b.totalRevenue - a.totalRevenue)
.slice(0, 10); // Top 10

Use Cases

Artist Dashboard

Display key metrics on artist's dashboard:

import { useEffect, useState } from 'react';

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

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

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

const { overview, topProducts, referrals } = analytics;

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

<div className="metrics">
<div className="metric">
<h3>Total Revenue</h3>
<p>${overview.totalRevenue.toFixed(2)}</p>
</div>
<div className="metric">
<h3>Your Payout</h3>
<p>${overview.artistPayout.toFixed(2)}</p>
</div>
<div className="metric">
<h3>Orders</h3>
<p>{overview.totalOrders}</p>
</div>
<div className="metric">
<h3>Items Sold</h3>
<p>{overview.totalItemsSold}</p>
</div>
</div>

<h2>Top Products</h2>
<table>
<thead>
<tr>
<th>Product</th>
<th>Revenue</th>
<th>Units Sold</th>
</tr>
</thead>
<tbody>
{topProducts.map(product => (
<tr key={product.productId}>
<td>{product.productName}</td>
<td>${product.totalRevenue.toFixed(2)}</td>
<td>{product.unitsSold}</td>
</tr>
))}
</tbody>
</table>

<h2>Referral Performance</h2>
<p>
Gallery referrals: {referrals.totalReferrals}
<br />
Conversions: {referrals.conversions} ({referrals.conversionRate.toFixed(1)}%)
<br />
Attributed revenue: ${referrals.attributedRevenue.toFixed(2)}
</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,
},
],
};

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

Export Analytics

Download analytics as CSV:

async function exportAnalytics(orgId: string, token: string) {
const res = await fetch(
`/api/gallery/artist/analytics?org_id=${orgId}`,
{
headers: { Authorization: `Bearer ${token}` },
}
);
const { analytics } = await res.json();

const csv = [
['Metric', 'Value'],
['Total Orders', analytics.overview.totalOrders],
['Total Revenue', analytics.overview.totalRevenue],
['Gallery Commission', analytics.overview.galleryCommission],
['Artist Payout', analytics.overview.artistPayout],
['Average Order Value', analytics.overview.averageOrderValue],
['Total Items Sold', analytics.overview.totalItemsSold],
[''],
['Top Products', ''],
['Product', 'Revenue', 'Units Sold'],
...analytics.topProducts.map(p => [
p.productName,
p.totalRevenue,
p.unitsSold,
]),
]
.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 = `analytics-${orgId}-${new Date().toISOString()}.csv`;
a.click();
}

Optimization Tips

Improve Conversion Rate

If referral conversion rate is low (<10%), try:

  • Optimize store: Ensure artist store has good product photos, descriptions
  • Offer exclusives: Products only available on artist store (not gallery)
  • Email list: Collect emails from gallery visitors for remarketing
  • Social proof: Add reviews, testimonials to artist store

Boost Top Products

Identify what's selling well and:

  • Create variations: Offer different sizes, colors of top sellers
  • Cross-promote: Bundle top products with slower movers
  • Increase inventory: Ensure top products stay in stock
  • Gallery features: Request spotlight or collection placement for top products

Increase Average Order Value

Encourage larger purchases:

  • Bundles: Offer product sets at slight discount
  • Free shipping threshold: "Free shipping on orders $75+"
  • Upsells: Suggest complementary products during checkout

Data Retention

Analytics data is stored indefinitely but:

  • Real-time updates: Metrics update within 1 hour of order status change
  • Historical accuracy: Past data never changes (no retroactive adjustments)
  • Date range limits: API returns max 1 year of data per query

For longer time ranges, make multiple API calls:

async function getYearlyAnalytics(orgId: string, year: number) {
const quarters = [
{ start: `${year}-01-01`, end: `${year}-03-31` },
{ start: `${year}-04-01`, end: `${year}-06-30` },
{ start: `${year}-07-01`, end: `${year}-09-30` },
{ start: `${year}-10-01`, end: `${year}-12-31` },
];

const results = await Promise.all(
quarters.map(q =>
fetch(
`/api/gallery/artist/analytics?org_id=${orgId}&start_date=${q.start}&end_date=${q.end}`,
{ headers: { Authorization: `Bearer ${token}` } }
).then(r => r.json())
)
);

// Combine quarterly results
return combineAnalytics(results);
}

Next Steps