Skip to content

Monthly follower growth rate chart on channel insights #383

Closed

Description

@paulocastellano

Problem

Channel insights show how many followers were gained in the selected range, but not whether that growth is healthy relative to the size of the account. 200 new followers means different things for a 2k and a 200k account. A monthly follower growth rate (net new followers over the month divided by followers at the start of the month) is the normalised number people look at over time.

Current state

  • Followers and net new followers are built per bucket in app/Actions/Analytics/BuildChannelMetricSeries.php (withFollowers() :189, net_followers is cumulative from the range baseline). Series ids are listed in app/Actions/Analytics/ListAvailableChannelMetrics.php:38.
  • The chart is resources/js/components/analytics/channel/ChannelMetricsCard.vue + ChannelMetricsChart.vue (@unovis stacked bar + line, analytics colour tokens, previous-period dashed).
  • Source of truth for daily follower counts: analytics_account_daily_snapshots.followers_count.
  • Date ranges and weekly bucketing: App\Support\Analytics\PeriodBuckets, ResolveAnalyticsRangePreset.

Tasks

  • Backend: new action BuildChannelFollowerGrowthRate (same app/Actions/Analytics/ conventions: data_get(), no $perPage-style params) returning one point per calendar month for the last 12 months (independent of the page's date range, but honouring the viewing user's time zone for month boundaries per the "User preferences" rules): {month, start_followers, end_followers, net_new, rate}.
  • Rate = (end - start) / start where start is the last known count before the month (or the first count inside it when no earlier one exists), null when start is 0 or unknown. Months with no data return null, not 0.
  • Mark the current month as partial (month to date) and style it differently.
  • Expose as a deferred prop on ChannelController@insights (deferred props need a skeleton empty state) and add a card/preset on the channel insights page. Hide it for networks with no follower collection (ListAvailableChannelMetrics).
  • Frontend: bar chart with @unovis, percent axis, tooltip showing +N followers and the rate, formats through @/date and Intl.NumberFormat with the active locale; analytics colour tokens, dark mode, mobile width (390px), screen-reader data table like the metrics card.
  • Copy under analytics.channel.* in all 16 locales; check longest locales do not wrap tabs/chips (extend the existing no-wrap browser test pattern).
  • If the follower history backfill issue lands, months before connect fill in automatically; until then show a "not enough history" state with how many months are available.

Data notes

DB / migration notes

  • No schema change. Compute in PHP from date + followers_count; do not use engine-specific date functions (DATE_TRUNC, DATE_FORMAT). Works on PostgreSQL and MySQL.
  • Fixtures never past 2038-01-19.

Tests

  • Unit/feature test for the action: normal month, month with no earlier snapshot, zero start, gaps, partial current month, week start irrelevant.
  • Time zone boundary test (user zone vs UTC).
  • Controller test: deferred prop present, absent for networks without followers.
  • Browser test with data-testid, ending in assertNoJavaScriptErrors().

Out of scope

  • Benchmarking against similar accounts or industry averages. We hold no benchmark data and will not fabricate it.
  • Forecasting future growth.
  • Workspace-level (multi-channel) growth rate; this is per channel only.

Activity

  1. paulocastellano commented on Oct 11, 2026

    @paulocastellano
    ContributorAuthor

    Shipped in #374.

    Channel insights now has a monthly follower growth rate chart covering the last 12 calendar months (BuildFollowerGrowthRateSeries), in the viewer's time zone. It loads as a deferred prop and only appears for networks that report follower counts. A month with no known starting count is left empty instead of showing a made-up rate.

    Not done, on purpose: separate styling for the current (partial) month and a low-precision flag for YouTube. The chart covers what we need for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions