Zuschauer-Monetarisierung (Viewer Donations & Tipping)
ZurΓΌck zur MOC - Map of Content
Status: π GEPLANT (Tournament Phase)
Viewer-Monetarisierung ist geplant fΓΌr das Breakout Tournament und spΓ€ter fΓΌr regelmΓ€Γige Sessions.
Konzept: Viewer Donations wΓ€hrend Live-Events
Beschreibung
WΓ€hrend des Breakout Tournaments (und spΓ€ter in Sessions) kΓΆnnen Zuschauer ihre Lieblingsartists, Jury-Creator oder die Plattform direkt unterstΓΌtzen mit Micro-Payments.
Γhnlich wie: Twitch Tips, YouTube Super Chat, Patreon, Ko-fi Donations
Psychologie
- Emotionale Connection: "Ich unterstΓΌtze meinen Lieblings-Artist"
- Status Signal: "Ich bin Platinum Fan" (Badge/Shout-out)
- FOMO: "Nur 5 Platinum Fans haben den Artist getagged!"
- Impulse: Live-Event erzeugt Emotion β sofortige UnterstΓΌtzung
Tiering-Modell (π GEPLANT)
β¬1 Tier: "Applause"
ββ What: Digitale Animation (π Heart, Clap, Fire, etc.)
ββ Duration: Instant
ββ Visibility: Alle Zuschauer sehen Animation
ββ Use Case: "Schnell einen KΓΌnstler unterstΓΌtzen"
β¬5 Tier: "Support"
ββ What: Username-Badge (z.B., "[Supporter] John")
ββ Duration: 1 Minute sichtbar im Chat
ββ Visibility: Nur Chat-Nutzer sehen Badge
ββ Use Case: "Mein Name sollte sichtbar sein"
β¬25 Tier: "VIP Supporter"
ββ What: Shout-out von Host
ββ Duration: WΓ€hrend Song des Artists
ββ Visibility: Alle Viewers im Stream
ββ Use Case: "Ich mΓΆchte dem Artist Hallo sagen!"
ββ Message: Custom text (up to 50 chars)
β¬100+ Tier: "Platinum Fan"
ββ What: Name-Drop vor Jury-Panel
ββ Duration: 10-sekunden Segment
ββ Visibility: Alle Viewers sehen dich mit deinem Namen
ββ Message: Custom intro (up to 100 chars)
ββ Use Case: "Ich bin der GRΓSSTE Fan!"
Alternative: Simpler Tier-Model (fΓΌr Phase 1)
β¬5: Quick Support (Heart Animation)
β¬25: Named Support (Shout-out)
β¬100+: Premium Supporter (Name + Custom Message)
Technische Implementierung (π GEPLANT)
Payment Flow
1. Viewer opens Donation Modal in Stream
2. Selects Tier (β¬5, β¬25, β¬100)
3. Optional: Writes custom message
4. Clicks "Donate"
5. Stripe Payment Intent created (embedded on stream page)
6. Viewer enters payment (Stripe hosted form or Apple Pay/Google Pay)
7. Payment completed β Webhook received
8. Supabase: Insert into `donations` table
9. Real-time Realtime Channel broadcasts to all viewers
10. Donation Wall updated (Live)
11. Host/Jury notified
12. Revenue Split calculated & stored
Database Schema (π GEPLANT)
CREATE TABLE donations (
id BIGSERIAL PRIMARY KEY,
session_id UUID REFERENCES sessions(id),
viewer_id UUID, -- Anonymous or Auth
target_type ENUM ('artist', 'creator', 'platform'), -- who gets tip?
target_id UUID, -- artist_id or creator_id
amount_eur_cents INT,
tier ENUM ('applause', 'support', 'vip', 'platinum'),
message TEXT,
payment_id VARCHAR (Stripe), -- stripe_payment_intent_id
status ENUM ('pending', 'succeeded', 'failed'),
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE donation_splits (
id BIGSERIAL PRIMARY KEY,
donation_id BIGINT REFERENCES donations(id),
recipient_type ENUM ('artist', 'jury_creator', 'platform'),
recipient_id UUID,
amount_eur_cents INT,
percentage INT, -- 60%, 20%, 20%
status ENUM ('pending', 'paid', 'failed')
);
Netlify Function (π GEPLANT)
// netlify/functions/processDonation.mts
export async function handler(event: HandlerEvent) {
if (event.httpMethod !== 'POST') {
return { statusCode: 405 };
}
const {
sessionId,
viewerId,
targetType,
targetId,
amountEurCents,
tier,
message,
stripePaymentIntentId,
} = JSON.parse(event.body!);
try {
// 1. Create Stripe Charge (if not already authorized)
const charge = await stripe.charges.create({
amount: amountEurCents,
currency: 'eur',
payment_method: stripePaymentIntentId,
});
if (charge.status !== 'succeeded') {
return { statusCode: 400, body: 'Payment failed' };
}
// 2. Insert Donation Record
const { data: donation, error: insertError } = await supabase
.from('donations')
.insert([
{
session_id: sessionId,
viewer_id: viewerId,
target_type: targetType,
target_id: targetId,
amount_eur_cents: amountEurCents,
tier,
message,
payment_id: charge.id,
status: 'succeeded',
},
])
.select()
.single();
if (insertError) throw insertError;
// 3. Calculate Split & Insert Donation_Splits
const artistShare = Math.floor(amountEurCents * 0.6);
const juryShare = Math.floor(amountEurCents * 0.2);
const platformShare = amountEurCents - artistShare - juryShare;
await supabase.from('donation_splits').insert([
{
donation_id: donation.id,
recipient_type: 'artist',
recipient_id: targetId,
amount_eur_cents: artistShare,
percentage: 60,
status: 'pending',
},
{
donation_id: donation.id,
recipient_type: 'jury_creator',
recipient_id: targetId, // Host Creator
amount_eur_cents: juryShare,
percentage: 20,
status: 'pending',
},
{
donation_id: donation.id,
recipient_type: 'platform',
amount_eur_cents: platformShare,
percentage: 20,
status: 'pending',
},
]);
// 4. Real-time Notification to Stream Viewers
supabase.realtime.broadcast({
event: 'new_donation',
payload: {
donation: {
id: donation.id,
tier,
message,
amount: amountEurCents,
viewerName: viewerId,
},
},
});
return {
statusCode: 200,
body: JSON.stringify({
success: true,
donationId: donation.id,
}),
};
} catch (error) {
console.error(error);
return {
statusCode: 500,
body: JSON.stringify({ error: String(error) }),
};
}
}
Viewer Experience (π GEPLANT)
During Tournament Stream
βββββββββββββββββββββββββββββββββββββββββββ
β TOURNAMENT LIVESTREAM β
βββββββββββββββββββββββββββββββββββββββββββ€
β β
β [Artist performing... Music plays] β
β β
β ββ Donation Wall (Right Sidebar) βββ β
β β π Platinum Fan: Max β β
β β "Go Artist_Name! π₯" β β
β β β β
β β VIP Supporter: Lisa β β
β β [Support Button] β¬5 β¬25 β¬100+ β β
β βββββββββββββββββββββββββββββββββββββ β
β β
β [Jury Panel scoring...] β
β [Chat Reactions...] β
β β
βββββββββββββββββββββββββββββββββββββββββββ
Donation Modal
ββββββββββββββββββββββββββββββββββ
β Support [Artist Name] β
ββββββββββββββββββββββββββββββββββ€
β β
β β€οΈ β¬5 - Applause β
β Quick animation visible β
β β
β π β¬25 - VIP Supporter β
β Your name + shout-out β
β Message: [Text field] β
β β
β π β¬100+ - Platinum Fan β
β Premium shout-out β
β Custom message (100 chars) β
β [Text field] β
β β
β [Donate] [Cancel] β
ββββββββββββββββββββββββββββββββββ
Revenue Impact & Projections (π GEPLANT)
Assumptions for Tournament Day
- Viewers: 500β2,000 concurrent
- Donation Rate: 1β3% of viewers
- Average Tier: 60% β¬5, 30% β¬25, 10% β¬100+
- Average Amount: ~β¬15 per donor
Calculation Example (1,000 concurrent viewers)
Viewers: 1,000
Donation Rate (2%): Γ 20 donors
Average Tier: β¬15 per donor
βββββββββββββββββββββββββββββββββ
Revenue: β¬300 per ~30min round
Per Tournament (4 rounds):
Total Donations: β¬300 Γ 4 = β¬1,200
Artist share (60%): β¬720
Jury Creators (20%): β¬240 (split among 5 = β¬48 each)
Platform (20%): β¬240
Stripe fees (2.9%): -β¬35
Net Platform: β¬205
Scaling Projection (Season 1+)
| Event | Expected Viewers | Donation Rate | Expected Revenue |
|---|---|---|---|
| Tournament Week 1 | 500β1,000 | 1β2% | β¬100β300 |
| Tournament Week 2 | 1,000β2,000 | 2β3% | β¬300β900 |
| Regular Session | 100β300 | 0,5β1% | β¬10β30 |
| Post-Tournament | 200β500 | 1β2% | β¬30β100 |
Annual Projection (if 4Γ tournaments + 100 sessions):
- β¬4,000 from tournaments
- β¬3,000 from sessions
- Total: ~β¬7,000/year from donations
Gamification Elements (π GEPLANT)
Leaderboard
TOP SUPPORTERS THIS TOURNAMENT
1. π Max (β¬200 total)
ββ 4 β¬ 100 donations
ββ "Go Artist_Name! π₯"
2. π₯ Lisa (β¬150 total)
ββ 1 β¬ 100 + 2 β¬ 25
ββ "Amazing performance!"
3. π₯ Alex (β¬100 total)
ββ 4 β¬ 25 donations
ββ Various messages
Badges & Rewards (π GEPLANT, fΓΌr spΓ€ter)
π Platinum Supporter Badge
"You've donated β¬100+ to breakout artists"
β€οΈ Heart of the Community
"Most donations in a single tournament"
π΅ Artist Champion
"Biggest supporter of [Artist Name]"
Anti-Fraud & Moderation (π GEPLANT)
Donation Validation:
ββ Stripe Verification (Always require valid payment method)
ββ Rate Limiting (Max 10 donations per viewer per session)
ββ Message Filtering (No spam, profanity, hateful content)
ββ Chargebacks: Hold disputed donations in escrow
ββ Suspicious Patterns: Alert admin if $X donated instantly
Message Moderation:
ββ Auto-filter profanity using API
ββ Report Inappropriate Messages
ββ Admin Approval for >β¬50 messages (optional)
ββ Blacklist users who abuse system
Fallback & Issues (π GEPLANT)
What if Stripe payment fails?
1. Donation initiated but Stripe times out
2. Show "Payment pending" state to viewer
3. Retry automatically (3 attempts)
4. If failed: Show error, option to retry manually
5. If success on retry: Show success + animation
6. If all fail: Refund & show "Try again later"
What if Real-time connection drops?
1. Donation still processes (backend is independent)
2. Real-time broadcast queues messages
3. When reconnected: Bulk broadcast pending donations
4. Viewers see "Loading donations..." β loads all
5. No donations lost, may be delayed 5β10 secs
Future Enhancements (Post-Season 1)
π Later:
ββ Donation Goals ("Raise β¬1,000 for Artist Fund")
ββ Recurring Monthly Support ("Sponsor this Artist")
ββ Donation Matching ("Double your impact!")
ββ Crowdfunding for Album Production
ββ Affiliate Revenue Sharing with Artists
ββ NFT Collectibles ("You donated to make this artist!")
Verweise
- MOC - Map of Content
- Revenue-Streams β All monetization channels
- Revenue-Splits β Full breakdown of who gets what
- Tournament-Ablauf β Where donations happen (Tournament)
- Strategische Entscheidungen β Decision framework