Platform Engagement Trends in 2025

insights
engagement
trends
Author

Julian Winternheimer

Published

December 1, 2025

Overview

In this analysis we’ll compare engagement metrics across Buffer’s supported platforms in 2025 to see which see the most engagement and how those metrics have changed over time. We used the median engagement rate where available as well as platform-specific metrics like views for YouTube and interaction counts for Bluesky and Mastodon.

What We Found

LinkedIn still leads all platforms with a median engagement rate of 6.2% in 2025, followed by Facebook at 5.6% and Instagram at 5.5%. Pinterest sits at 4.0%, while Threads and X bring up the rear at 3.6% and 2.5% respectively.

X saw the largest year-over-year increase, with median engagement rates jumping 44% from 2.0% in 2024 to 2.8% in 2025. Pinterest also showed strong growth, up 23% from 3.2% to 3.9%. Facebook improved more modestly, increasing 11% from 5.0% to 5.6%.

On the flip side, Instagram saw a significant decline in engagement rates, dropping from 7.3% in 2024 to 5.4% in 2025. Threads’ and LinkedIn’s engagement rates declined year-over-year as well.

YouTube’s median views more than tripled from 86 in 2024 to 268 in 2025, though it’s hard to say whether this reflects actual performance improvements or changes in the user base. Bluesky’s median interactions decreased slightly from 5 to 4, while Mastodon held steady at 3 interactions per post.

Data Collection

The SQL queries below return median engagement metrics by month and platform for posts from 2025. We’re calculating the median in SQL to efficiently aggregate across all posts while accounting for the fact that some accounts naturally get more engagement than others.

For platforms with engagement_rate metrics (LinkedIn, Facebook, X, Instagram, Threads, Pinterest, TikTok), we use that standardized metric. For YouTube, we track median views. For Bluesky, we sum comments, likes, and reposts. For Mastodon, we sum shares, favorites, and comments.

Code
# Query for engagement rate platforms
sql_engagement_rate <- "
  select
    profile_service
    , date_trunc(sent_at, month) as month
    , approx_quantiles(
        case
          when profile_service = 'instagram' then safe_divide(engagements, reach) * 100
          else engagement_rate
        end, 100)[offset(50)] as median_metric
    , count(*) as n_posts
  from dbt_buffer.publish_updates
  where sent_at >= '2025-01-01'
    and sent_at < '2025-12-01'
    and profile_service in ('twitter', 'linkedin', 'facebook', 'instagram',
      'threads', 'pinterest', 'tiktok')
    and case
          when profile_service = 'instagram' then safe_divide(engagements, reach) is not null
            and safe_divide(engagements, reach) > 0
          else engagement_rate is not null
            and engagement_rate > 0
        end
  group by 1, 2
  order by 1, 2
"

# Query for YouTube (views)
sql_youtube <- "
  select
    profile_service
    , date_trunc(sent_at, month) as month
    , approx_quantiles(views, 100)[offset(50)] as median_metric
    , count(*) as n_posts
  from dbt_buffer.publish_updates
  where sent_at >= '2025-01-01'
    and sent_at < '2025-12-01'
    and profile_service = 'youtube'
    and views is not null
    and views > 0
  group by 1, 2
  order by 1, 2
"

# Query for Bluesky (comments + likes + reposts)
sql_bluesky <- "
  select
    profile_service
    , date_trunc(sent_at, month) as month
    , approx_quantiles(comments + likes + reposts, 100)[offset(50)] as median_metric
    , count(*) as n_posts
  from dbt_buffer.publish_updates
  where sent_at >= '2025-01-01'
    and sent_at < '2025-12-01'
    and profile_service = 'bluesky'
    and (comments + likes + reposts) is not null
    and (comments + likes + reposts) > 0
  group by 1, 2
  order by 1, 2
"

# Query for Mastodon (shares + favorites + comments)
sql_mastodon <- "
  select
    profile_service
    , date_trunc(sent_at, month) as month
    , approx_quantiles(shares + favorites + comments, 100)[offset(50)] as median_metric
    , count(*) as n_posts
  from dbt_buffer.publish_updates
  where sent_at >= '2025-01-01'
    and sent_at < '2025-12-01'
    and profile_service = 'mastodon'
    and (shares + favorites + comments) is not null
    and (shares + favorites + comments) > 0
  group by 1, 2
  order by 1, 2
"

# get data from BigQuery
monthly_engagement_rate <- bq_query(sql = sql_engagement_rate)
monthly_youtube <- bq_query(sql = sql_youtube)
monthly_bluesky <- bq_query(sql = sql_bluesky)
monthly_mastodon <- bq_query(sql = sql_mastodon)

# Add metric_type column and combine
monthly_engagement_rate$metric_type <- "engagement_rate"
monthly_youtube$metric_type <- "views"
monthly_bluesky$metric_type <- "total_interactions"
monthly_mastodon$metric_type <- "total_interactions"

monthly_engagement <- bind_rows(
  monthly_engagement_rate,
  monthly_youtube,
  monthly_bluesky,
  monthly_mastodon
)
Code
# Year-over-year queries
sql_yoy_engagement_rate <- "
  select
    profile_service
    , extract(year from sent_at) as year
    , approx_quantiles(
        case
          when profile_service = 'instagram' then safe_divide(engagements, reach) * 100
          else engagement_rate
        end, 100)[offset(50)] as median_metric
    , count(*) as n_posts
  from dbt_buffer.publish_updates
  where sent_at >= '2024-01-01'
    and sent_at < '2026-01-01'
    and profile_service in ('twitter', 'linkedin', 'facebook', 'instagram',
      'threads', 'pinterest', 'tiktok')
    and case
          when profile_service = 'instagram' then safe_divide(engagements, reach) is not null
            and safe_divide(engagements, reach) > 0
          else engagement_rate is not null
            and engagement_rate > 0
        end
  group by 1, 2
  order by 1, 2
"

sql_yoy_youtube <- "
  select
    profile_service
    , extract(year from sent_at) as year
    , approx_quantiles(views, 100)[offset(50)] as median_metric
    , count(*) as n_posts
  from dbt_buffer.publish_updates
  where sent_at >= '2024-01-01'
    and sent_at < '2026-01-01'
    and profile_service = 'youtube'
    and views is not null
    and views > 0
  group by 1, 2
  order by 1, 2
"

sql_yoy_bluesky <- "
  select
    profile_service
    , extract(year from sent_at) as year
    , approx_quantiles(comments + likes + reposts, 100)[offset(50)] as median_metric
    , count(*) as n_posts
  from dbt_buffer.publish_updates
  where sent_at >= '2024-01-01'
    and sent_at < '2026-01-01'
    and profile_service = 'bluesky'
    and (comments + likes + reposts) is not null
    and (comments + likes + reposts) > 0
  group by 1, 2
  order by 1, 2
"

sql_yoy_mastodon <- "
  select
    profile_service
    , extract(year from sent_at) as year
    , approx_quantiles(shares + favorites + comments, 100)[offset(50)] as median_metric
    , count(*) as n_posts
  from dbt_buffer.publish_updates
  where sent_at >= '2024-01-01'
    and sent_at < '2026-01-01'
    and profile_service = 'mastodon'
    and (shares + favorites + comments) is not null
    and (shares + favorites + comments) > 0
  group by 1, 2
  order by 1, 2
"

# get year-over-year data
yoy_engagement_rate <- bq_query(sql = sql_yoy_engagement_rate)
yoy_youtube <- bq_query(sql = sql_yoy_youtube)
yoy_bluesky <- bq_query(sql = sql_yoy_bluesky)
yoy_mastodon <- bq_query(sql = sql_yoy_mastodon)

# Add metric_type column and combine
yoy_engagement_rate$metric_type <- "engagement_rate"
yoy_youtube$metric_type <- "views"
yoy_bluesky$metric_type <- "total_interactions"
yoy_mastodon$metric_type <- "total_interactions"

yoy_engagement <- bind_rows(
  yoy_engagement_rate,
  yoy_youtube,
  yoy_bluesky,
  yoy_mastodon
)

Data Preparation

Using median metrics is particularly important here because it’s a more robust measure when comparing across accounts of different sizes. A few viral posts or accounts with extremely high engagement won’t skew the results as much as they would if we simply took the average.

We’ll analyze platforms in groups based on their primary metric: - engagement rate for LinkedIn, Facebook, X, Instagram, Threads, Pinterest, TikTok, views for YouTube, and total engagements for Bluesky and Mastodon.

Code
# convert month to date
monthly_engagement <- monthly_engagement %>%
  mutate(month = as.Date(month))

Top Platforms by Engagement Rate

Code
# calculate overall summary statistics for engagement rate platforms
monthly_engagement %>%
  filter(metric_type == "engagement_rate") %>%
  group_by(profile_service) %>%
  summarise(
    avg_median_engagement_rate = percent(mean(median_metric / 100, na.rm = TRUE), accuracy = 0.01),
    total_posts = comma(sum(n_posts))
  ) %>%
  arrange(desc(avg_median_engagement_rate))
# A tibble: 7 × 3
  profile_service avg_median_engagement_rate total_posts
  <chr>           <chr>                      <chr>      
1 linkedin        6.17%                      10,158,498 
2 facebook        5.56%                      29,304,073 
3 instagram       5.46%                      20,648,455 
4 tiktok          4.55%                      4,911,032  
5 pinterest       3.95%                      1,729,782  
6 threads         3.57%                      6,121,761  
7 twitter         2.51%                      17,741,236 

LinkedIn leads with an average median engagement rate of 6.2%, followed by Facebook at 5.6% and Instagram at 5.5%. TikTok comes in fourth at 4.6%, while Pinterest sits at 4.0%. Threads and X lag behind at 3.6% and 2.5% respectively.

Median Engagement Rates Over Time

The plot below shows how engagement rates have changed throughout 2025 for platforms with engagement_rate metrics. LinkedIn sits at the top but has been trending downward a bit. Facebook showed strong engagement through mid-year before declining in the fall.

X and Pinterest’s engagement rates have increased throughout the year.

Platform Comparison

We can view these lines separately for each platform to better see the individual trends.

Year Over Year Comparison

We’ll also compare overall median engagement rates between 2024 and 2025 to see how platform performance has evolved.

Code
# calculate percent change from 2024 to 2025 for engagement rate platforms
yoy_change_engagement_rate <- yoy_engagement_rate_data %>%
  select(profile_service, year, median_metric) %>%
  pivot_wider(names_from = year, values_from = median_metric, names_prefix = "year_") %>%
  mutate(
    pct_change = (year_2025 - year_2024) / year_2024,
    change_label = percent(pct_change, accuracy = 0.1)
  ) %>%
  arrange(desc(pct_change))

yoy_change_engagement_rate
# A tibble: 7 × 5
  profile_service year_2024 year_2025 pct_change change_label
  <chr>               <dbl>     <dbl>      <dbl> <chr>       
1 twitter              1.96      2.83     0.444  44.4%       
2 pinterest            3.15      3.87     0.229  22.9%       
3 facebook             5         5.56     0.112  11.2%       
4 tiktok               4.35      4.48     0.0299 3.0%        
5 linkedin             6.35      6.06    -0.0456 -4.6%       
6 threads              4.36      3.57    -0.181  -18.1%      
7 instagram            7.27      5.36    -0.263  -26.3%      

The year-over-year comparison shows some clear distinctioins in the platforms. X leads the pack with a 44% increase in the median engagement rate, though this might be due to a change in the way engagement rate is calculated. X is followed by Pinterest at 23% and Facebook at 11%. TikTok stayed relatively flat with just a 3% gain.

On the other side, Instagram, Threads, and LinkedIn all declined. Sample sizes grew significantly in 2025, with most platforms seeing 2-3x more posts analyzed. This gives us more confidence in the 2025 numbers, though it also means we should be cautious about making direct comparisons when the underlying user bases may have changed substantially.

Summary Table

The table below consolidates all key metrics for engagement rate platforms, including year-over-year comparison, 2025 trends, and overall performance.

Platform 2024 Rate 2025 Rate YoY Change Jan 2025 Latest 2025 2025 Trend 2024 Posts 2025 Posts
linkedin 6.35% 6.06% -4.6% 6.55% 5.33% -18.7% 8,462,795 10,158,498
facebook 5.00% 5.56% 11.2% 4.95% 4.76% -3.8% 17,836,483 29,304,073
instagram 7.27% 5.36% -26.3% 6.22% 5.30% -14.7% 4,651,609 20,648,455
tiktok 4.35% 4.48% 3.0% 4.49% 4.03% -10.2% 1,140,073 4,911,032
pinterest 3.15% 3.87% 22.9% 3.63% 5.00% 37.7% 1,674,860 1,729,782
threads 4.36% 3.57% -18.1% 3.49% 3.34% -4.3% 1,585,184 6,121,761
twitter 1.96% 2.83% 44.4% 2.11% 4.29% 103.3% 7,323,189 17,741,236

YouTube Shorts

For YouTube Shorts we used median views instead of the number of engagements. The average median for YouTube videos in 2025 was around 288 views, but this increased significantly through the course of the year.

Summary Statistics

Code
# Summary for YouTube
monthly_engagement %>%
  filter(profile_service == "youtube") %>%
  group_by(profile_service) %>%
  summarise(
    avg_median_views = comma(mean(median_metric, na.rm = TRUE)),
    total_posts = comma(sum(n_posts))
  )
# A tibble: 1 × 3
  profile_service avg_median_views total_posts
  <chr>           <chr>            <chr>      
1 youtube         288              3,085,596  

Year Over Year Comparison

The median views more than tripled from 86 in 2024 to 268 in 2025. However, this change likely reflects shifts in Buffer’s YouTube user base rather than improved performance across the board. The number of posts also increased by about 20%, which suggests that more YouTube creators are using Buffer in 2025.

Bluesky Engagement

Bluesky’s engagement metric is the sum of comments, likes, and reposts. We do not collect reach or any engagement rate metric for Bluesky, so this will have to do. With a median of around 4 interactions per post, Bluesky shows modest but consistent engagement levels.

Summary Statistics

Code
# Summary for Bluesky
monthly_engagement %>%
  filter(profile_service == "bluesky") %>%
  group_by(profile_service) %>%
  summarise(
    avg_median_interactions = comma(mean(median_metric, na.rm = TRUE), accuracy = 0.1),
    total_posts = comma(sum(n_posts))
  )
# A tibble: 1 × 3
  profile_service avg_median_interactions total_posts
  <chr>           <chr>                   <chr>      
1 bluesky         4.1                     9,296,475  

Year Over Year Comparison

Bluesky’s median interactions dropped slightly from 5 in 2024 to 4 in 2025. However, the volume of posts nearly quadrupled, suggesting that as more users joined Buffer for Bluesky posting, the user base shifted toward accounts with smaller followings. This is a natural pattern as any platform matures and adoption broadens beyond early adopters.

Mastodon Engagement

Mastodon’s engagement metric is the sum of shares, favorites, and comments. The median number of engagements is 3 and has not changed at all throughout the course of the year.

Summary Statistics

Code
# Summary for Mastodon
monthly_engagement %>%
  filter(profile_service == "mastodon") %>%
  group_by(profile_service) %>%
  summarise(
    avg_median_interactions = comma(mean(median_metric, na.rm = TRUE), accuracy = 0.1),
    total_posts = comma(sum(n_posts))
  )
# A tibble: 1 × 3
  profile_service avg_median_interactions total_posts
  <chr>           <chr>                   <chr>      
1 mastodon        3.0                     626,156    

Year Over Year Comparison

There is no change year over year either.

Caveats

This analysis uses median metrics to account for differences in account sizes, but there are still important limitations to consider.

First, we’re using different metrics for different platforms, which makes direct comparisons difficult. Engagement rates measure different things than absolute interaction counts or view counts. A 5% engagement rate on LinkedIn isn’t directly comparable to 4 interactions on Bluesky or 268 views on YouTube.

Second, engagement metrics are influenced by many factors beyond platform algorithms, including content quality, posting time, audience demographics, and account maturity. We’re also comparing accounts of vastly different sizes and niches within each platform.

Third, the dramatic changes in some metrics - particularly X’s 44% increase and YouTube’s 212% jump - likely reflect changes in the user base or metric definitions rather than genuine performance improvements. As Buffer’s user base grows and shifts, the composition of accounts changes, which can have a bigger impact on medians than actual platform performance.

Finally, our data only includes Buffer users, which may not be representative of all users on each platform. Buffer users tend to be more sophisticated about social media strategy than average users, which could skew these numbers in either direction.