Revenue Metrics
The Score layout is purpose-built for metrics: one big number front and center, a label, and an optional badge for trend or status. Use it to keep the one number that matters today always in view.
Basic metric push
curl -X POST "YOUR_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "job_id": "mrr-today", "layout": "score", "metric": "$48,210", "message": "Monthly Recurring Revenue", "secondaryMetric": "+4.2%", "status": "running", "accentColor": "#00FF88", "icon": "dollarsign.circle.fill" }'Updating throughout the day
The best pattern for a live metric is to push an update whenever the value changes from a Stripe webhook, a scheduled query, or a cron job. Because Island Pulse auto-updates in place, the number on your Lock Screen changes without any additional setup.
From a Python script
import requests
WEBHOOK_URL = "YOUR_WEBHOOK_URL"
def update_mrr(current_mrr: float, prev_mrr: float): change_pct = ((current_mrr - prev_mrr) / prev_mrr * 100) if prev_mrr else 0 trend = f"+{change_pct:.1f}%" if change_pct >= 0 else f"{change_pct:.1f}%"
requests.post(WEBHOOK_URL, json={ "job_id": "mrr-today", "layout": "score", "metric": f"${current_mrr:,.0f}", "message": "Monthly Recurring Revenue", "secondaryMetric": trend, "status": "running", "accentColor": "#00FF88" if change_pct >= 0 else "#FF3B30" })From a Stripe webhook
Forward Stripe’s customer.subscription.created and charge.succeeded events to a small handler:
from flask import Flask, requestimport requests, os
app = Flask(__name__)PULSE_URL = os.environ["ISLAND_PULSE_URL"]
@app.route("/stripe-webhook", methods=["POST"])def stripe_webhook(): event = request.get_json()
if event["type"] in ("charge.succeeded", "customer.subscription.created"): amount = event["data"]["object"].get("amount", 0) / 100 requests.post(PULSE_URL, json={ "job_id": "stripe-live", "layout": "score", "metric": f"${amount:,.0f}", "message": event["type"].replace(".", " ").title(), "status": "success", "accentColor": "#34C759", "icon": "creditcard.fill" })
return "", 200Goal tracking with the Progress layout
When you’re tracking against a daily or monthly goal, the Progress layout conveys how far along you are at a glance:
{ "job_id": "daily-goal", "layout": "progress", "message": "$8,420 of $10,000 goal", "metric": "84%", "progress": 0.84, "status": "running", "accentColor": "#00CFFF"}Hit goal:
{ "job_id": "daily-goal", "layout": "progress", "message": "Daily goal hit! $11,240", "metric": "100%", "progress": 1.0, "status": "success"}Multiple KPIs (Pro)
Track several numbers simultaneously with distinct job keys. Each gets its own Live Activity:
curl -X POST "YOUR_WEBHOOK_URL" -d '{"job_id":"mrr","layout":"score","metric":"$48k","message":"MRR",...}'curl -X POST "YOUR_WEBHOOK_URL" -d '{"job_id":"signups","layout":"score","metric":"1,204","message":"Signups today",...}'curl -X POST "YOUR_WEBHOOK_URL" -d '{"job_id":"churn","layout":"score","metric":"1.2%","message":"Churn rate",...}'Character limits for the Score layout
Keep metric text short so it renders at full size. Values over 12 characters automatically shrink.
| Field | Ideal | Maximum |
|---|---|---|
metric | ≤ 8 chars | 16 chars (scaled) |
message | ≤ 20 chars | 45 chars (scaled) |
secondaryMetric | ≤ 8 chars | 10 chars |
Good: $48,210, 1,204, 142ms, 4.2%
Too long: $1,240,000.00 → trim to $1.24M