DEV Community

Daniel Pertu
Daniel Pertu

Posted on

A 120,000-subscriber channel whose videos get 3,000 views is priced as a 46,000-subscriber one

Nakodo suggests what a brand should offer each creator it finds. Two different questions are involved and it took a rewrite to see that they were different:

  • What is the fee? That follows views. A brand is buying the people who watch, and nobody else.
  • What is the ask? That follows size. Asking a 500,000-subscriber channel for "a quick mention in return for the product" is an insult, and the size bands everybody uses, nano, micro, mid-tier, macro, mega, are defined in followers. Our guide to micro-influencers says out loud that these bands are a convention rather than a standard, and we still have to pick boundaries.

So the app needs to move between followers and views in both directions. That is three small functions with one sharp edge.

The curve

Reach as a share of followers is not a constant. It falls as an account grows, and it falls differently on each platform. These are medians of the creators the app has stored, with the query that produced them left in the file so the next person can rerun it:

// What a post actually reaches, as a share of followers, and how that falls as
// an account grows: medians of the creators Nakodo has found (October 2026,
// n = 4,300).
//   select platform, percentile_disc(0.5) within group (order by
//     median_views::numeric / subscriber_count) from channels
//   where median_views is not null and subscriber_count > 1000 group by 1;
const EXPECTED_REACH: Record<CreatorPlatform, [number, number][]> = {
  youtube:   [[1_000, 0.085], [10_000, 0.078], [100_000, 0.059], [1_000_000, 0.039]],
  instagram: [[1_000, 0.37],  [10_000, 0.095], [100_000, 0.095], [1_000_000, 0.059]],
  tiktok:    [[1_000, 0.285], [10_000, 0.071], [100_000, 0.048], [1_000_000, 0.029]],
};
Enter fullscreen mode Exit fullscreen mode

Four control points per platform, not a fitted formula, because a table is something you can argue with in review and a magic exponent is not.

Interpolating on the right scale

Between control points, linear interpolation in follower space is wrong: the gap from 10,000 to 100,000 is one tenth of the x-axis and most of the interesting creators. Both axes are interpolated geometrically instead, which is a straight line on a log-log plot:

export function expectedViews(platform: Platform, followers: number): number {
  const points = EXPECTED_REACH[creatorPlatform(platform)];
  const n = Math.max(MIN_FOLLOWERS, followers);
  const ratio = (): number => {
    if (n <= points[0][0]) return points[0][1];
    for (let i = 1; i < points.length; i++) {
      const [f0, r0] = points[i - 1];
      const [f1, r1] = points[i];
      if (n <= f1) return r0 * (r1 / r0) ** (Math.log(n / f0) / Math.log(f1 / f0));
    }
    return points[points.length - 1][1];
  };
  return n * ratio();
}
Enter fullscreen mode Exit fullscreen mode

The expression is the whole trick: r0 * (r1 / r0) ** t where t is the position of n between f0 and f1 measured in logs. At t = 0 you get r0, at t = 1 you get r1, and in between the ratio moves by equal factors for equal factors of followers. A YouTube channel with 40,000 subscribers comes out at about 2,637 views, and one with 120,000 at about 6,852.

Clamping at both ends is deliberate. Below 1,000 followers we do not price at all, and above a million the curve stops falling rather than heading for zero.

The inverse, because reach only ever goes up

Now the other direction: a creator whose posts get 3,000 views has roughly the following of someone with what number of followers? There is no closed form worth writing for a piecewise geometric curve, so:

export function followersForViews(platform: Platform, views: number): number {
  let low = MIN_FOLLOWERS;
  let high = 100_000_000;
  for (let i = 0; i < 50; i++) {
    const mid = Math.sqrt(low * high);
    if (expectedViews(platform, mid) < views) low = mid;
    else high = mid;
  }
  return Math.round(low);
}
Enter fullscreen mode Exit fullscreen mode

Two details worth copying. The midpoint is the geometric mean, Math.sqrt(low * high), which halves the search in the same log space the curve lives in, so the convergence is even across five orders of magnitude. And the loop count is fixed at 50 rather than testing for a tolerance: expectedViews is monotonic in followers, 50 geometric halvings of a range from 1,000 to 100,000,000 is far past double precision, and a bounded loop cannot hang when someone passes in a number nobody expected.

followersForViews("youtube", 3000) is 46,317.

The one asymmetric line

Here is where the two questions meet, and the comment is longer than the code on purpose:

// Followers to place a creator by: their following, brought down to what
// their posts actually reach when that is less. A channel with 40,000
// subscribers whose videos get 1,000 views reaches as many people as a
// 13,000-subscriber one, and that reach is what the brand is buying, so that
// is the size it is asked as. Never the other way round: a creator who does
// better than others their size earns more for it, because their fee follows
// their views, but isn't asked for more than their following would suggest.
function sizeBy(a: Audience): number | null {
  if (a.platform === "web") return a.followers;
  const p = creatorPlatform(a.platform);
  if (a.followers === null) return a.views === null ? null : followersForViews(p, a.views);
  if (!a.views) return a.followers;
  return Math.min(a.followers, followersForViews(p, a.views));
}
Enter fullscreen mode Exit fullscreen mode

Math.min and not an average, and never Math.max. A channel with 120,000 subscribers whose recent videos get 3,000 views is placed at 46,317, which is on the other side of the 100,000 boundary: it is asked as a micro creator, not a mid-tier one. Our vetting guide tells brands to check that recent views look sensible against the subscriber count; sizeBy is that check with a number attached.

The asymmetry is the point. A creator who outperforms their following is paid for it, because the fee is computed from views directly:

const RATES = { youtube: { mention: { base: 40, perThousand: 16 }, /* ... */ } };
Enter fullscreen mode Exit fullscreen mode

At market rates, a mention costs a fixed part for the work plus a rate per 1,000 views. That is the same arithmetic as our free sponsorship cost calculator, which turns a CPM into a fee and a quote back into a CPM. For a 40,000-subscriber channel, the fee lands at about 80 pounds at its typical 2,637 views and about 60 pounds if those videos only get 1,000. What does not happen is the same channel being asked to make a dedicated video because its subscriber count says mid-tier while its views say otherwise.

Reach is a curve, its inverse is three lines of bisection, and the only subjective decision in the whole file is which direction the Math.min points.

Top comments (0)