Skip to main content

Referral Tracking API

The Referral Tracking API enables attribution of gallery visitors who purchase from individual artist stores. Artists receive 100% of attributed sales (minus Stripe fees) with no gallery commission.

How It Works

  1. User visits gallery - Views artist's work on gallery.artbase.studio
  2. Clicks to artist store - Visits artist.artbase.studio
  3. 30-day cookie set - Attribution cookie stored
  4. Purchase tracked - If user purchases within 30 days, sale is attributed
  5. Artist keeps 100% - No gallery commission on attributed sales

Endpoints

Track Referral

Records when a gallery visitor clicks through to an artist's individual store.

Endpoint: POST /api/gallery/referral/track

Authentication: None

Request Body:

{
"org_id": "org_abc123"
}

Request Parameters:

FieldTypeRequiredDescription
org_idstringYesArtist organization UUID

Response:

{
"success": true,
"referral": {
"id": "ref_abc123",
"orgId": "org_abc123",
"sessionId": "session_xyz789",
"createdAt": "2024-01-15T10:30:00Z",
"expiresAt": "2024-02-14T10:30:00Z"
}
}

Response Fields:

FieldTypeDescription
successbooleanAlways true on success
referral.idstringReferral record UUID
referral.orgIdstringArtist organization ID
referral.sessionIdstringUnique session identifier
referral.createdAtstringISO 8601 timestamp
referral.expiresAtstringAttribution window end (30 days)

Example Request:

curl -X POST https://gallery.artbase.studio/api/gallery/referral/track \
-H "Content-Type: application/json" \
-d '{
"org_id": "org_abc123"
}'

Cookie Set:

Response sets a cookie for tracking:

Cookie: gallery_ref=session_xyz789
Max-Age: 2592000 (30 days)
HttpOnly: true
Secure: true (production)
SameSite: Lax

Error Responses:

StatusErrorDescription
400Organization ID requiredMissing org_id
404Organization not foundInvalid org_id

Attribution Window

30-Day Window

Referrals are valid for 30 days from the click:

Day 0: User clicks from gallery to artist store
Day 1-30: Purchases attributed to gallery referral
Day 31+: Purchases not attributed
const REFERRAL_WINDOW_DAYS = 30;
const cookieMaxAge = REFERRAL_WINDOW_DAYS * 24 * 60 * 60; // 2,592,000 seconds

cookieStore.set('gallery_ref', sessionId, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: cookieMaxAge,
});

Conversion Tracking

When a purchase occurs on an artist store within 30 days:

  1. Check cookie - Look for gallery_ref cookie
  2. Verify referral - Confirm referral exists and hasn't expired
  3. Create conversion - Record in gallery_referral_conversions
  4. Track revenue - Store order total for analytics
// Example conversion tracking
async function trackConversion(sessionId: string, orderId: string, amount: number) {
const referral = await getReferralBySession(sessionId);

if (!referral) return; // No active referral
if (new Date() > new Date(referral.expiresAt)) return; // Expired

await createConversion({
referralId: referral.id,
orderId: orderId,
amount: amount,
convertedAt: new Date(),
});
}

Benefits for Artists

100% Revenue on Attributed Sales

Artist keeps full sale amount on attributed conversions:

Gallery sale:

$100 product
├─ Artist receives: $88 (88%)
└─ Gallery commission: $12 (12%)
Customer pays: ~$115 (includes fees)

Attributed sale (within 30 days of referral):

$100 product
├─ Artist receives: $97 (~97%)
└─ Stripe fee: ~$3 (3%)
Customer pays: $100

Marketing Value

Gallery acts as a marketing channel:

  • Discovery - Expose work to new audiences
  • Trust - Gallery curation adds credibility
  • No cost - Only pay 12% on gallery sales
  • Direct relationship - Build customer list on artist store

Client Integration

Track clicks to artist store:

export function ProductPage({ product }) {
const handleVisitStore = async () => {
// Track referral
await fetch('/api/gallery/referral/track', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
org_id: product.org_id,
}),
});

// Redirect to artist store
window.location.href = `https://${product.organizations.slug}.artbase.studio`;
};

return (
<div>
<h1>{product.name}</h1>
<p>By {product.organizations.name}</p>
<button onClick={handleVisitStore}>
Visit Artist Store
</button>
</div>
);
}

Artist Store Checkout

Check for attribution cookie:

import { cookies } from 'next/headers';

export async function POST(request: Request) {
const cookieStore = await cookies();
const referralSession = cookieStore.get('gallery_ref')?.value;

if (referralSession) {
// Track conversion
await trackConversion(referralSession, orderId, orderTotal);
}

// Process order normally
// ...
}

Analytics

Artists can view referral performance via the Artist Analytics API:

{
"referrals": {
"totalReferrals": 42,
"conversions": 8,
"conversionRate": 19.05,
"attributedRevenue": 680.00
}
}

Admins can view gallery-wide referral metrics via the Admin Analytics API.


Privacy & Compliance

Data Stored

The referral system stores:

  • ✅ Organization ID (which artist)
  • ✅ Session ID (anonymous identifier)
  • ✅ Timestamps (created, expires)
  • ✅ Conversion data (order ID, amount)
  • ❌ Personal information (names, emails, addresses)

GDPR Compliance

  • Cookie consent: Inform users of tracking cookies
  • Data retention: Referral records expire after 30 days
  • Right to deletion: Users can clear cookies to opt out
export function CookieBanner() {
return (
<div className="cookie-banner">
<p>
We use cookies to track referrals and improve your experience.
By continuing, you consent to our use of cookies.
</p>
<button onClick={() => acceptCookies()}>Accept</button>
<button onClick={() => rejectCookies()}>Reject</button>
</div>
);
}

Testing

Test Referral Flow

  1. Create referral:

    curl -X POST http://localhost:3000/api/gallery/referral/track \
    -H "Content-Type: application/json" \
    -d '{"org_id": "org_abc123"}'
  2. Verify cookie set:

    Check response headers for Set-Cookie: gallery_ref=...
  3. Make test purchase on artist store within 30 days

  4. Verify conversion tracked in database:

    SELECT * FROM gallery_referral_conversions
    WHERE referral_id = 'ref_abc123';

Next Steps