Why a store and not a live call
Three of the four screens people actually want are impossible to answer live:- Follower history. No platform returns the follower count you had last Tuesday. If nobody measured it that day, it’s gone for good.
- Engagement accumulation. “Half the engagement arrives in the first 6 hours” requires the same post measured repeatedly as it ages.
- Comparison to the previous period. Needs both periods on hand.
Cadence
The collector refreshes a post more often when its numbers are still moving, and backs off as it settles:
Two consequences worth knowing:
- A post older than 180 days is frozen. Its last reading stays on record and is never refreshed again. Engagement on a six-month-old post doesn’t move, and re-reading your whole archive forever would be the one thing that makes this system grow without bound.
- A post the platform no longer knows — deleted, or turned private — is frozen on its last reading rather than erased. Your history stays intact.
Freshness, and saying it out loud
Every analytics response carrieslastSyncAt and nextSyncAt. Show them.
A number without its reading time looks like real time, and the first time it
disagrees with the platform’s own app — which it will, because the two were read
at different moments — it reads as a bug rather than a sync cycle that hasn’t
run yet.
On top of PlugKit’s own cadence, the platforms add their own lag: Instagram
insights settle over roughly 24 hours, and a view counted at minute one is not
final at minute two anywhere.
History depth
This bounds the read, not the collection. Data keeps being recorded either
way, so moving to Pro reveals a past that was already there — retroactively. A
request that reaches further back than your plan allows isn’t rejected: it is
clamped, and the response says so.
What each platform exposes
WhatsApp and Telegram have no posts, so they have no analytics.
A few platform truths that shape what you’ll see:
- Instagram retired
impressionsfor media in favour ofviews. Old posts may carry one and not the other. - TikTok requires the
video.listanduser.info.statsscopes. They are not retroactive: an account connected before those scopes were added has no analytics until it reconnects. Everything else about it keeps working, so the symptom is empty charts, not an error. - YouTube returns totals since publication, not a day-by-day series. The daily breakdown lives in the YouTube Analytics API, which requires a separate Google audit.
- X is metered per read. See below.
X, and anything else that bills per call
X charges for every API read, so it plays by different rules:- Nothing is polled until
xAnalyticsEnabledis set on the account (PATCH /v1/accounts/{id}/x-billing). - Once enabled, a post is refreshed at most once a day, whatever the plan and whatever its age. The hourly hot window doesn’t apply.
- Posts are not discovered on X — only what you published through PlugKit is tracked. Listing a timeline costs a billed read per page, forever, to find posts you already know about.
- When the spend cap is reached, background collection stops silently. It isn’t an error — it’s the limit in force, yours or the $20 default. Publishing is never blocked by it.
This is a general mechanism, not an X special case. Any platform that starts
billing per read gets the same treatment: opt-in, once a day, under the cap.
Turning it off
Collection can be stopped entirely on a deployment withANALYTICS_ENABLED=false. Scheduled posts keep going out — the two loops are
separate on purpose.