RevenueHogdocs
Dashboard

Live feed

Every badge in the live feed, the App Store notification, Stripe event or Google Play notification behind it, what each amount means, and how the feed works.

The live feed (/feed, Live feed in the sidebar) is the per-event view of every connected source: Apple's App Store Server Notifications V2, Stripe's billing events for connected Stripe accounts, and Google Play's real-time developer notifications for connected Android apps. One row per verified event, the moment it arrives.

What a row shows

Each row shows the time (12m ago, with the exact timestamp in your timezone on hover), the event badge, the app icon, the product (the App Store Connect reference name such as "Pro Yearly" when cached, else the raw product ID), a caption with the app, the country and a note (for example 7d trial), and a signed USD amount: positive for money in, negative for refunds. Trials and churn move no money, so their amount column is left blank. Sandbox events carry a sandbox marker.

A purchase whose Family Sharing copies were collapsed into it shows a person mark with a count, for example ×2 ("Shared with 2 family members"). A refund request row also shows how RevenueHog answered Apple's consumption request.

Rows with an Apple transaction ID have a › chevron ("View customer") that opens customer lookup for that transaction. Stripe rows (IDs starting sub_, pi_ or cs_) have no chevron. Clicking a row opens the event detail.

App Store amounts come from the signed transaction inside each notification (Apple reports prices in milliunits of the local currency; 39990 means 39.99). Stripe amounts come from the invoice, payment or refund in the currency's minor units (cents, or whole yen for zero-decimal currencies). Both are converted to USD with daily ECB reference rates, the same conversion the metrics page describes. Some churn payloads carry no price; those rows show no amount rather than a guess.

Header line

On the unfiltered, all-apps feed the top line reads $X this week, $Y this month. The week starts Monday at local midnight and the month on the 1st, in your timezone. These totals are report-first: days Apple's sales report covers use the report's gross figure, and the unreported tail comes from live events. A value that is not a clean non-negative number is hidden. The line is absent while an app is selected, because the totals are org-wide.

Filter chips

ChipURLShows
All/feedEvery mapped event kind
Buys?filter=buysBUY, RENEW, CONV
Trials?filter=trialsTRIAL
Churn?filter=churnCHURN and RISK (billing failure belongs alongside churn)
Refunds?filter=refundsRFND, RFRQ, RREV, RDEC (Stripe disputes included)

The topbar app filter scopes the feed to one app (?app=). The period control does not affect the feed.

Days, totals and expected revenue

Rows are grouped under sticky day headers in your timezone (TODAY, YESTERDAY, then dates). Each header carries the day's net total (green when positive, red when negative) and, when that day started trials, / +$X new trials: what those trials will charge if they convert. The pending figure is never part of the total. A quiet TODAY shows "Nothing yet today" (or "No buys yet today" and so on for a chip) and "New events land here live".

On the unfiltered all-apps feed, an EXPECTED TODAY band sits above the first day when anything is due: +$X · N renewals · N trials converting. Expand it for the rules: subscriptions due to renew and free trials due to convert before midnight in your timezone, with auto-renew still on. Renewals count at their current term price, conversions at the price the trial converts to. Cancelled subscriptions and trials are excluded. Apple can bill hours before a deadline; once a charge lands it moves from expected to actual. It is a projection: billing retries, late cancellations and price changes can move it.

The newest row is highlighted for its first minute.

Loading and refresh

The feed loads 50 events at a time and fetches older pages as you scroll (or press Load older). If a page fails, "Couldn't load older events." appears with Retry. The page refreshes every 30 seconds while the tab is visible and you have interacted with it in the last two minutes; leave it idle and refreshing stops, then resumes as soon as you return.

Empty states: "Nothing here yet. Events land the second your store sends them." on All, or No buys yet. (and so on) on a chip.

Event badges

BadgeAmountSource eventWhat it means
BUYgreen, +$App Store: SUBSCRIBED, ONE_TIME_CHARGE, OFFER_REDEEMED. Stripe: invoice.paid (new subscription), checkout.session.completed (one-time payment). Google Play: SUBSCRIPTION_PURCHASED, ONE_TIME_PRODUCT_PURCHASEDA new or returning purchase: a paid subscription start, a resubscribe, a one-time purchase, or an offer redeemed as a first or repeat purchase.
TRIALcyan, $0.00App Store: SUBSCRIBED (free-trial transaction). Stripe: customer.subscription.created (trialing). Google Play: SUBSCRIPTION_PURCHASED (free-trial offer phase)A free trial started. Detected from the signed transaction's offer type or a subscription created in trial, with the trial length shown (for example "7d trial").
RENEWgreen, +$App Store: DID_RENEW, OFFER_REDEEMED (UPGRADE/DOWNGRADE). Stripe: invoice.paid (renewal or plan change). Google Play: SUBSCRIPTION_RENEWED, SUBSCRIPTION_RECOVEREDA renewal billed successfully, including recoveries from billing retry and plan changes on an already-active subscription.
CONVgreen, +$App Store: DID_RENEW (first renewal of a trial). Stripe: invoice.paid (first paid invoice after a trial). Google Play: SUBSCRIPTION_RENEWED (first paid renewal after a trial)Trial converted to paid. No source has a dedicated conversion event; see below.
CHURNredApp Store: EXPIRED, GRACE_PERIOD_EXPIRED, REVOKE, DID_CHANGE_RENEWAL_STATUS (AUTO_RENEW_DISABLED). Stripe: customer.subscription.updated (cancel at period end), customer.subscription.deleted. Google Play: SUBSCRIPTION_CANCELED, SUBSCRIPTION_EXPIRED, SUBSCRIPTION_REVOKEDThe subscription ended (expired, grace period ran out, access revoked) or the user turned auto-renew off, shown as "Unsubscribed", since they keep access until the period ends.
CANCELnoneA CHURN (auto-renew off) on a subscription still inside its free trialThe user cancelled before converting, so no paying customer was lost. Noted "Trial cancelled".
RFNDamber, −$App Store: REFUND. Stripe: refund.created, charge.dispute.closed (lost). Google Play: voided purchase (refund or chargeback)Money went back to the customer. Partial Stripe refunds carry the partial amount. Subtracts from LTV.
RFRQorange, $0.00App Store: CONSUMPTION_REQUEST. Stripe: charge.dispute.createdThe customer asked Apple for a refund, or opened a chargeback. Not lost revenue yet, so it moves no money. Apple re-sends this while the case is open; the feed shows one row per transaction.
RREVgreen, +$App Store: REFUND_REVERSED. Stripe: charge.dispute.funds_reinstatedA granted refund was reversed, or Stripe reinstated a disputed charge. Restores the revenue the RFND took away.
RDECgreen, $0.00App Store: REFUND_DECLINED. Stripe: charge.dispute.closed (won)Apple declined the refund request, or you won a dispute. You keep the money; it closes out the case.
PLANblue, $0.00App Store: DID_CHANGE_RENEWAL_PREF. Stripe: customer.subscription.updated (price change)The customer queued a plan change (upgrade, downgrade or crossgrade). The money moves at the upgrade transaction or the next renewal.
PRICamber, $0.00App Store: PRICE_INCREASEYou raised the price (PENDING = awaiting consent, ACCEPTED = consented). Applies at future renewals.
RISKred, $0.00App Store: DID_FAIL_TO_RENEW. Stripe: invoice.payment_failed. Google Play: SUBSCRIPTION_IN_GRACE_PERIOD, SUBSCRIPTION_ON_HOLDBilling failed: retry, or a grace period with access intact. The leading edge of churn, but not counted as churn.
FAMILYblue, $0.00App Store: SUBSCRIBED with inAppOwnershipType FAMILY_SHAREDSomeone gained access through the purchaser's Family Sharing group. A real entitlement, not a second sale. Only purchases are relabelled; a family-shared churn is still churn.
VERSnoneApp Store Connect version state changes (from the App Store Connect webhook or the sync)An App Review lifecycle change for an app version.

Only BUY, RENEW, CONV and RREV add money, and only RFND takes it away. The rest are $0 on purpose. A refund request, a declined refund, a queued plan change, a price increase and a billing failure move no money by themselves; whatever they eventually do to revenue arrives through a later renewal and the daily subscription snapshot, so counting them here would double-count the same dollars.

Unknown or future event types (Apple's TEST and RENEWAL_EXTENDED, Stripe events outside the list above, and anything a source ships next) are recorded but not rendered, so a new type can never break ingestion. See also event types.

Trial to paid detection

Apple does not send a "trial converted" notification. A conversion arrives as an ordinary DID_RENEW. Two signals find it.

The primary one is lineage: RevenueHog has the trial's SUBSCRIBED start on file and this is the first renewal of that same subscription, so it is a conversion.

The fallback matters because you usually connect RevenueHog in the middle of subscriptions that are already running, and it never saw their trial starts. The renewal transaction is then read on its own: if the very first period, from the original purchase to this one, was materially shorter than a full billing term, that short first period was the trial. A seven-day trial against a monthly term, or a month against an annual one, falls well under half a term, while a genuine renewal's first period is a full term. The check only applies to the first renewal.

Either way the row is badged CONV ("Trial converted") and later renewals are plain RENEWs. On Stripe, the first paid invoice of a subscription whose trial start is on file is the conversion.

Sandbox and Family Sharing

Every event carries its environment. The feed shows production events by default. Sandbox events (development builds, Apple's accelerated-clock test subscriptions, Stripe test mode) are hidden unless you turn on Show sandbox events, the toggle beside the chips, which saves the Sandbox in feed preference (also under Settings → Notifications). Sandbox push alerts are a separate toggle, also off by default. Family Sharing duplicates are hidden unless Family Sharing in feed is on. See notification preferences.

No events yet?

Events only arrive when something happens. For App Store apps, wire server notifications per the setup guide, then make a sandbox purchase or use Send sandbox test on the app detail page. Stripe events arrive through the connected account's webhook, or within a few minutes through polling when no webhook is set up (see Connect Stripe).

Last updated on

On this page