Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Analyze Pollinations Stripe revenue, pack purchases, and balance-bucket spending patterns with Tinybird production data.
.claude/skills/pollinations-spending-analysis/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 70% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 915% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 196% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 36% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 11% | 0% |
pollinations repository root.jq and sops.enter.pollinations.ai/observability/scripts/tb-prod.sh "<sql>" (below writtenas tb-prod.sh). It uses the production read token from SOPS; the staging workspace has no real revenue.
Revenue queries must filter successful Stripe checkout events so asynchronous payment methods are counted exactly once.
bashtb-prod.sh "SELECT toStartOfWeek(timestamp) AS week, round(sum(amount_cents) / 100, 2) AS revenue_usd, count() AS purchases FROM stripe_event WHERE payment_status = 'paid' AND event_type IN ('checkout.session.completed', 'checkout.session.async_payment_succeeded') AND timestamp >= now() - INTERVAL 90 DAY GROUP BY week ORDER BY week DESC FORMAT JSON" | jq '.data'
bashtb-prod.sh "SELECT timestamp, user_id, session_id, amount_cents / 100 AS amount, currency, payment_method FROM stripe_event WHERE payment_status = 'paid' AND event_type IN ('checkout.session.completed', 'checkout.session.async_payment_succeeded') ORDER BY timestamp DESC LIMIT 100 FORMAT JSON" | jq '.data'
bashtb-prod.sh "SELECT user_id, round(sum(amount_cents) / 100, 2) AS revenue_usd, count() AS purchases FROM stripe_event WHERE payment_status = 'paid' AND event_type IN ('checkout.session.completed', 'checkout.session.async_payment_succeeded') AND timestamp >= now() - INTERVAL 30 DAY GROUP BY user_id ORDER BY revenue_usd DESC LIMIT 50 FORMAT JSON" | jq '.data'
bashtb-prod.sh "SELECT toStartOfWeek(start_time) AS week, splitByChar(':', selected_meter_slug)[-1] AS meter_source, sum(total_price) AS total_spend, count() AS requests FROM generation_event_v2 WHERE start_time >= now() - INTERVAL 60 DAY AND environment = 'production' GROUP BY week, meter_source ORDER BY week DESC FORMAT JSON" | jq '.data'
generation_event_v2 spend (pack_spend, selected_meter_slug) says which bucket was consumed, not how it was funded. pack_balance is credited by Stripe purchases and auto-top-ups, but also by BYOP markup and community-model rewards (paid into the payer's bucket, shared/billing/track-helpers.ts) and some quest rewards. So pack spend ≠ cash. And Stripe checkout rows alone miss auto-top-ups, which never create a checkout.session.* event. To separate cash from earned funding, reconcile each source on its own and don't add figures with different monetary bases:
pollen_credited (stripe_event, payment_status = 'paid')amount_usd (principal credited — see below)No cash purchase ≠ non-payment or abuse; pack spend ≠ proof of cash.
Auto-top-up amount_usd in D1 is the Pollen principal credited; Stripe fees and taxes sit on top. Gross cash is in Tinybird stripe_event as payment_intent.succeeded rows with an empty user_id (auto top-ups are not attributed there); per user, fetch the invoice by stripe_invoice_id and use amount_paid. Keep principal, gross payment, tax, refunds and net revenue as separate numbers.
Define a past price change from the code deployed at the time, not the PR title or announcement — an "X% cheaper" announcement can coexist with a same-day multiplier change that cancels it. Confirm billed unit prices in generation_event_v2:
bashtb-prod.sh "SELECT toDate(start_time) AS day, round(avg(total_price), 6) AS avg_unit_price, count() AS requests FROM generation_event_v2 WHERE model_used = '<model>' AND start_time BETWEEN '<before>' AND '<after>' GROUP BY day ORDER BY day FORMAT JSON" | jq '.data'
Provider cost, priceMultiplier markup and pack-credit promotions move independently; check all three. Keep cash paid separate from Pollen credited — a Pollen discount doesn't change cash buying power. Note who was exposed before the payment event you're explaining and any simultaneous changes.
For "these users pay more" or "X caused conversion" claims, define the comparison first:
rewards that require a payment. Contribution rewards (PR/quest merges) are fine; payment-triggered rewards are not.
compare it only with another cohort measured the same way, or use a fixed per-user window ("first 7 days after signup").
after. If most paid first, the reward didn't drive conversion.
stripe_event is the source of truth for pack-purchase revenue analytics.generation_event_v2 records Pollen consumption, not cash revenue.user_id, so revenue and usage can be joined directly.daily_stripe_revenue pipe applies the same paid-event filter.of record (Nov 2025–Jan 2026) and is retired. Do not combine historical Polar and Stripe totals without checking the cutoff for overlap.
Always state the date window, and prefer revenue share (% of total_price) for strategic claims.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 10,759 | 23,943 | +123% | 1 | 1 | 0% | 1,497 | 2,552 | +70% | 0 | 0 | — |
case-02 | fail→pass | 4,979 | 11,654 | +134% | 1 | 1 | 0% | 233 | 2,366 | +915% | 0 | 0 | — |
case-03 | pass→fail | 23,695 | 43,427 | +83% | 1 | 1 | 0% | 3,735 | 1,995 | -47% | 0 | 0 | — |
case-04 | fail→pass | 10,341 | 17,436 | +69% | 1 | 1 | 0% | 1,368 | 4,054 | +196% | 0 | 0 | — |
case-05 | fail→fail | 12,900 | 11,788 | -9% | 1 | 1 | 0% | 922 | 2,165 | +135% | 0 | 0 | — |
case-06 | fail→pass | 29,424 | 16,510 | -44% | 1 | 1 | 0% | 2,439 | 3,324 | +36% | 0 | 0 | — |
case-07 | fail→pass | 13,439 | 5,750 | -57% | 1 | 1 | 0% | 2,050 | 2,282 | +11% | 0 | 0 | — |
case-08 | fail→pass | 15,767 | 19,744 | +25% | 1 | 1 | 0% | 1,970 | 2,982 | +51% | 0 | 0 | — |
case-09 | fail→pass | 13,814 | 7,185 | -48% | 1 | 1 | 0% | 2,145 | 2,584 | +20% | 0 | 0 | — |
case-10 | fail→fail | 13,169 | 8,375 | -36% | 1 | 1 | 0% | 2,121 | 2,909 | +37% | 0 | 0 | — |
case-11 | pass→pass | 21,539 | 16,727 | -22% | 1 | 1 | 0% | 1,680 | 3,858 | +130% | 0 | 0 | — |
case-12 | pass→pass | 18,587 | 11,669 | -37% | 1 | 1 | 0% | 1,911 | 3,242 | +70% | 0 | 0 | — |
case-13 | fail→pass | 12,695 | 19,693 | +55% | 1 | 1 | 0% | 1,706 | 2,758 | +62% | 0 | 0 | — |
case-14 | fail→pass | 16,001 | 15,344 | -4% | 1 | 1 | 0% | 2,044 | 3,869 | +89% | 0 | 0 | — |
case-15 | fail→pass | 24,823 | 14,755 | -41% | 1 | 1 | 0% | 2,597 | 3,779 | +46% | 0 | 0 | — |
case-16 | fail→pass | 15,011 | 7,579 | -50% | 1 | 1 | 0% | 2,231 | 2,678 | +20% | 0 | 0 | — |
case-17 | pass→pass | 31,696 | 48,737 | +54% | 1 | 1 | 0% | 2,993 | 3,802 | +27% | 0 | 0 | — |
case-18 | fail→pass | 23,705 | 14,080 | -41% | 1 | 1 | 0% | 1,374 | 2,197 | +60% | 0 | 0 | — |
case-19 | fail→fail | 15,637 | 15,789 | +1% | 1 | 1 | 0% | 1,398 | 4,226 | +202% | 0 | 0 | — |
case-20 | fail→pass | 15,747 | 25,525 | +62% | 1 | 1 | 0% | 1,864 | 3,132 | +68% | 0 | 0 | — |
case-21 | fail→pass | 25,736 | 17,155 | -33% | 1 | 1 | 0% | 2,078 | 2,956 | +42% | 0 | 0 | — |
case-22 | pass→pass | 13,557 | 13,262 | -2% | 1 | 1 | 0% | 2,025 | 3,827 | +89% | 0 | 0 | — |
case-23 | pass→pass | 15,769 | 21,858 | +39% | 1 | 1 | 0% | 2,334 | 2,995 | +28% | 0 | 0 | — |
case-24 | pass→pass | 7,568 | 5,773 | -24% | 1 | 1 | 0% | 1,163 | 2,233 | +92% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted, and 21 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +54 percentage points is the difference between those two pass rates over the 21 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/17/2026 | +64% |
| gemini-3.6-flash | verified | 8/9/2026 | +55% |
Other measured skills in the registry, with their headline benchmark lift.