---
id: agencias/redes-sociais-organicas
industry: Marketing agencies
usage: widely used
effort: medium
grain: Post (ranking) and profile x day (account), rolled up to week and month
---

# Organic social media

Reach, engagement, top posts and followers for each client, with the history the API does not keep and the same yardstick on every network.

## Executive summary

**For:** Agencies that deliver social media and need to report each client's organic growth.

**What it solves**

- Reach and engagement in the report match what the client sees in the app.
- Follower history exists even after the API only shows today's number.
- The top post of the month comes from the same yardstick on every network, with no job posts or ads mixed in.

**Why it matters:** The social report is a content agency's most visible deliverable and the first one to be challenged. APIs change metrics without notice, do not keep past followers and each network names reach differently. Without a fixed yardstick per client, the number moves from one month to the next for technical reasons and the meeting turns into explaining the spreadsheet.

**Business questions it answers**

- What was each client's best post this month, and why?
- How many followers did the client gain this month, by network?
- Was September's engagement better than August's?
- Reels, carousel or static: what works for this client?
- How many posts did we publish per client against the contract?

**What you need**

- Instagram, LinkedIn, Facebook Pages and TikTok connected per client profile
- A daily snapshot of followers and profile stored from day one
- The yardstick agreed with each client: reach or views, and what goes into the ranking

**What you get**

- A table per post with format, reach, views, interactions and engagement rate
- A daily series per profile with followers, gains and reach
- Month big numbers against the previous month, on the same yardstick
- An AI agent that answers about organic without mixing it with paid media

## Detailed

### The problem

Each network delivers organic data its own way: Instagram replaced impressions with views, LinkedIn calls reach unique impressions and TikTok has no reach at all. Followers and profile data are only today's number, so whoever did not store history cannot say how many followers the client gained in March. And whoever sums daily reach delivers a number larger than the real one, which the client does not recognize in the app.

### Business rules

1. **Reach does not add up.** Reach counts unique people. Summing reach across days or posts counts the same person more than once. For the month, use the 28-day reach the network itself deduplicates (instagram_insights_rolling_days28 on the last day) or show reach per post. Interactions, likes, comments and views do add up. (Avoid: Summing daily reach for the month.)
2. **One declared yardstick per network.** Agree on the coverage metric with the client and keep it. On Instagram, the API discontinued impressions in April 2025 and now delivers views. LinkedIn has no post views: the approximation is impressionCount, with uniqueImpressionsCount as reach. Store in a column which source field produced each number. (Avoid: Comparing Instagram views with LinkedIn reach on the same chart without saying so.)
3. **Followers is a snapshot, not a sum.** Followers is the value on the last day of the period. Follower gain is end minus the end of the previous period, or the sum of daily gains when the network provides them (on LinkedIn, organic plus paid followerGains). Repeating the latest number on every past row creates a flat history that never happened. (Avoid: Using today's followers_count for every month.)
4. **Store the daily snapshot starting now.** Profile, followers and cumulative video and page metrics are current state only. Write one row per profile per day after each sync, with the reference date set to the previous day in the client's time zone and an idempotent write (running twice the same day updates the same row). Never overwrite the history table. (Avoid: Relying on the API to show followers from past months.)
5. **A post belongs to its publishing month.** Post metrics (media_insights, post_statistics) are cumulative over the post's life and keep growing after the month. In the ranking and the post count, the post stays in the month it was published, and the report states up to which date metrics were read. Daily account metrics (insights_rolling_day) stay on the insight day. (Avoid: Mixing post totals with daily account totals in the same number.)
6. **Format comes from two fields.** On Instagram, media_type alone does not separate Reels: VIDEO with media_product_type REELS is Reels, CAROUSEL_ALBUM is Carousel, IMAGE is Static and STORY is Story. Stories last 24 hours and have their own metrics: they stay out of the ranking and the post target, counted separately. (Avoid: Classifying every VIDEO as Reels and adding Stories to posts.)
7. **Ranking with brand content only.** Remove from the ranking job and recruiting posts, posts with no organic statistics (dark posts and ad variations on LinkedIn) and boosted content when the yardstick is organic. Interactions per thousand followers (interactions / followers at period end x 1000) compares posts across profiles of different sizes. (Avoid: Ranking everything the API returns by impressions.)
8. **Engagement rate recalculated.** Engagement rate = interactions / reach, or / views if that is the client's yardstick, computed from period sums and never as the average of daily or per-post rates. TikTok provides neither reach nor saves: there the rate is (likes + comments + shares) / views, and the report says the yardstick is different. (Avoid: Averaging each post's rate.)
9. **Organic does not come from ads.** Profile reach and engagement do not exist in Meta Ads tables, which are paid media. If the client's profile is not connected, the answer is that there is no organic data, not a number taken from Facebook Ads. A piece produced is also not a piece published. (Avoid: Answering profile reach with ad reach.)
10. **A join that does not drop days.** Daily insights and follower counts sync at different times and one lags the other. Join the two series by day keeping the days from both (FULL OUTER JOIN), otherwise the most recent day disappears from the chart. (Avoid: Plain join between insights and followers.)

### Yardstick per network

The field that answers each metric, per network. Declare the official yardstick in the client's context.

- **Instagram · post** → Reach (`media_insights.reach`)
- **Instagram · account, month** → Deduplicated reach (`insights_rolling_days28.reach`)
- **Instagram · post** → Views (replaces impressions) (`media_insights.views`)
- **Instagram · format** → Reels, Carousel, Static, Story (`media_type + media_product_type`)
- **LinkedIn · post and page** → Impressions (`totalShareStatistics.impressionCount`)
- **LinkedIn · post and page** → Reach (`totalShareStatistics.uniqueImpressionsCount`)
- **LinkedIn · day** → Followers gained (`followerGains.organicFollowerGain + paidFollowerGain`)
- **LinkedIn · page** → Page views (`totalPageStatistics.views.allPageViews.pageViews`)
- **TikTok · video** → Engagement over views (`(like + comment + share) / view_count`)
- **Facebook Pages · day** → Organic impressions (`page_posts_impressions_organic`)

### Definitions

| Metric | Definition |
|---|---|
| Monthly reach | Instagram: the account's 28-day reach on the last day of the month; LinkedIn: page unique impressions in the month; never a sum of daily reach |
| Views | Instagram: views; LinkedIn: impressionCount; TikTok: view_count; summed over the period |
| Interactions | Instagram: total_interactions; LinkedIn: likes + comments + shares + clicks; summed over the period |
| Engagement rate | sum of interactions / sum of the declared base (reach or views), over the same period and the same set of posts |
| Followers | snapshot value on the last day of the period, per profile |
| Followers gained | followers at period end minus followers at the end of the previous period, or the sum of daily gains when the network provides them |
| Interactions per thousand followers | post interactions / profile followers at period end x 1000 |
| Posts published | posts with a publish date in the period (on LinkedIn, lifecycleState = PUBLISHED); Stories counted separately |

### Pitfalls

- **Reach the client does not recognize.** Summing daily reach for the month produced a reach well above what the app showed, because the same person was counted on several days. How to avoid: Use the network's 28-day reach or reach per post.
- **Impressions that vanished.** After April 2025 Instagram's impressions field stopped arriving and the report started showing zero, as if the profile had stopped. How to avoid: Switch to views and record the change date in the context.
- **Followers with no past.** The table kept only today's total, repeated on every row. The growth chart came out flat and the monthly gain, zero. How to avoid: Daily snapshot in append from day one.
- **Job posts on top of the ranking.** Recruiting posts boosted by HR led the LinkedIn impressions ranking and hid the brand content. How to avoid: Filter job posts and posts with no organic statistics.
- **Zero rows on LinkedIn.** Filtering the page aggregate with share = '' returned zero rows, because the field comes as null, not empty. Breaking down by country with pageStatisticsByGeoCountry also zeroed months where the array came empty. How to avoid: Test null and empty together and use the totalPageStatistics totals.
- **Last day missing.** Insights and followers synced at different times and a plain join dropped the most recent day. How to avoid: A join that keeps the days of both series.

Validated on real data: On Nekt's own Instagram, the sum of daily reach over 28 days came out between 1.6 and 1.9 times the 28-day reach the network itself deduplicates, across three different windows. Whoever sums daily reach reports almost twice the people reached.

### Acceptance test

- [ ] For one profile and one closed month, views and interactions match the network's native dashboard or the client's reporting tool (difference below 2%).
- [ ] No monthly reach is a sum of daily reach: monthly reach equals the network's 28-day reach on the last day.
- [ ] Followers at each month end come from that day's snapshot, and month end minus previous month end equals followers gained.
- [ ] Stories do not appear in the ranking, and the sum of posts by format equals total posts published.
- [ ] The posts table has one row per post and per network.

### Context document

```text
Organic social media
- The organic source is the profile's own (Instagram, Facebook Pages, LinkedIn organic, TikTok). Meta Ads tables are paid media and never answer profile reach or engagement. With no organic source for the client, say there is no data.
- Reach does not add up across days or posts. Monthly reach = the network's 28-day reach on the last day, or reach per post.
- Coverage yardstick per network: Instagram = views (impressions was discontinued in April 2025); LinkedIn = impressionCount, with uniqueImpressionsCount as reach; TikTok = view_count.
- Engagement rate = sum of interactions / sum of the client's declared base, over the same period. TikTok has no reach or saves.
- Followers = snapshot value on the last day of the period. Followers gained = end minus end of the previous period.
- A post belongs to its publishing month; post metrics are cumulative up to the read date, which must be stated.
- Instagram format: media_type + media_product_type. Stories stay out of the post ranking.
- The ranking excludes job and recruiting posts and posts with no organic statistics.
- On LinkedIn, the page aggregate in daily_share_statistics is the row with share and ugcPost null or empty.
Per-client exceptions:
- <client>: official yardstick is <views | reach>; engagement rate over <base>.
- <client>: Instagram has no connector; monthly numbers come from <reporting tool>, validated through <month>.
- <client>: posts with <term> in the caption stay out of the ranking.
```

### Variations

- **Content pillar:** Classify each post into a pillar from caption words or hashtags and compare engagement by pillar.
- **Organic plus paid:** Cost per follower = spend on follower campaigns / followers gained on the same network and day.
- **Comments with AI:** Comment sentiment per post, for the brand health section of the report.
