Reflecting on the Past Year: A LinkedIn Year in Review (2023)

code
rtip
linkedin
Author

Steven P. Sanderson II, MPH

Published

January 4, 2024

Introduction

As we close the door on another year, it’s always a good time to look back and reflect on the past 12 months. And what better way to do that than with a LinkedIn Year in Review?

Whether you’re a job seeker, a business owner, or just someone who enjoys staying connected with their professional network, LinkedIn is an invaluable tool for staying up to date with the latest trends and opportunities in your field. And as we wrap up 2023, now is the perfect time to take a look at how you’ve been using LinkedIn and see where you can improve.

So what did your LinkedIn Year in Review have in store for you? Here are just a few of the things you might have seen:

  • A summary of your activity on LinkedIn, including how many people you’ve connected with, how many posts you’ve shared, and how many likes, comments, and shares your content has received.
  • A breakdown of the industries and job titles of the people you’ve connected with, which can give you a good idea of the types of people you’ve been spending the most time interacting with.
  • A summary of your skills and endorsements, as well as which skills are most in demand in your industry.

All of these insights can be incredibly valuable as you start planning for the year ahead. With this information in hand, you can start looking for new opportunities, strengthening your existing relationships, and building new ones. And with the start of the new year, it’s a perfect time to set new goals and improve your LinkedIn profile.

If you haven’t yet checked out your LinkedIn Year in Review, don’t wait any longer! Log in to your account and take a look. And while you’re there, why not make a resolution to be more active on LinkedIn in the coming year? The more you put into your professional network, the more you’ll get out of it.

So let’s make the most of this new year, take advantage of the insights from your LinkedIn Year in Review, and make the most of your professional network. Here’s to a successful, connected, and productive 2024!

I have done a lot of work on this already, it is not comprehensive but it is enough to understand what is happening, and I used a lot of functionality from the {healthyverse}

Don’t forget you can also see my package and GitHub development wrap up on my year in review 2023

Analysis

I will do this in chunks, as it will be easier to digest. First of course you have to get your data. I am not going to go over this process as there are many a great link just a search away.

Let’s load in those libraries and read the files in.

library(dplyr)
library(readxl)
library(lubridate)
library(timetk)
library(tidyr)
library(janitor)
library(stringr)
library(ggplot2)
library(healthyR.ts)
library(knitr)
library(kableExtra)

fp <- "linkedin_content.xlsx"

engagement_tbl <- read_excel(fp, sheet = "ENGAGEMENT") %>%
  clean_names() %>%
  mutate(date = mdy(date)) %>% 
  mutate(`Engagement Rate` = (engagements / impressions) * 100) %>%
  filter_by_time(
    .date_var = date,
    .end_date = "2023-12-31"
  )

top_posts_tbl <- read_excel(fp, sheet = "TOP POSTS", skip = 1) %>%
  clean_names()

followers_tbl <- read_excel(fp, sheet = "FOLLOWERS", skip = 2) %>%
  clean_names() %>%
  mutate(date = mdy(date)) %>%
  filter_by_time(
    .date_var = date,
    .end_date = "2023-12-31"
  )

demographics_tbl <- read_excel(fp, sheet = "DEMOGRAPHICS") %>%
  clean_names()

Now let’s take a look at that data.

glimpse(engagement_tbl)
Rows: 365
Columns: 4
$ date              <date> 2023-01-01, 2023-01-02, 2023-01-03, 2023-01-04, 202…
$ impressions       <dbl> 4872, 3735, 10360, 12217, 27036, 26084, 8720, 2753, …
$ engagements       <dbl> 34, 17, 51, 80, 173, 124, 32, 17, 80, 54, 106, 135, …
$ `Engagement Rate` <dbl> 0.6978654, 0.4551539, 0.4922780, 0.6548252, 0.639887…
glimpse(top_posts_tbl)
Rows: 50
Columns: 7
$ post_url_1          <chr> "https://www.linkedin.com/feed/update/urn:li:activ…
$ post_publish_date_2 <chr> "2/16/2023", "2/16/2023", "3/16/2023", "1/24/2023"…
$ engagements         <dbl> 281, 227, 220, 194, 181, 172, 160, 145, 138, 124, …
$ x4                  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ post_url_5          <chr> "https://www.linkedin.com/feed/update/urn:li:activ…
$ post_publish_date_6 <chr> "2/16/2023", "1/5/2023", "1/17/2023", "1/24/2023",…
$ impressions         <dbl> 43951, 38656, 34402, 32505, 25205, 24916, 22656, 2…
glimpse(followers_tbl)
Rows: 365
Columns: 2
$ date          <date> 2023-01-01, 2023-01-02, 2023-01-03, 2023-01-04, 2023-01…
$ new_followers <dbl> 11, 13, 17, 16, 26, 15, 14, 18, 14, 9, 11, 23, 6, 13, 5,…
glimpse(demographics_tbl)
Rows: 30
Columns: 3
$ top_demographics <chr> "Job titles", "Job titles", "Job titles", "Job titles…
$ value            <chr> "Data Scientist", "Data Analyst", "Software Engineer"…
$ percentage       <chr> "0.05210459977388382", "0.03567609563469887", "0.0223…

We are really only going to focus on the engagement_tbl and the followers_tbl as this is more of a time series analysis.

Ok, so let’s see how my Impressions, Engagements, and Engagement Rate have been.

engagement_tbl %>%
  pivot_longer(cols = -date) %>%
  mutate(name = str_to_title(name)) %>%
  plot_time_series(
    .facet_vars = name,
    .value = value,
    .date_var = date,
    .interactive = FALSE,
    .smooth = FALSE,
    .title = "LinkedIn Stats Time Series Plot"
  ) +
  theme_minimal()

followers_tbl %>%
  plot_time_series(
    .value = new_followers,
    .date_var = date,
    .interactive = FALSE,
    .smooth = FALSE,
    .title = "LinkedIn Stats Time Series Plot - New Followers"
  ) +
  theme_minimal()

Let’s look at a cumulative view of things.

engagement_tbl %>%
  summarise_by_time(
    .date_var = date,
    .by = "month",
    `Cumulative Impressions` = sum(impressions),
    `Cumulative Engagements` = sum(engagements)
  ) %>%
  mutate(
    `Cumulative Impressions` = cumsum(`Cumulative Impressions`),
    `Cumulative Engagements` = cumsum(`Cumulative Engagements`)
  ) %>%
  slice(1:12) %>%
  pivot_longer(cols = -date) %>%
  mutate(name = str_to_title(name)) %>%
  ggplot(aes(x = date, y = value)) +
  geom_col() +
  facet_wrap(~ name, scales = "free") +
  labs(
    x = "Date",
    y = "Value",
    title = "LinkedIn Stats Time Series Plot"
  ) +
  theme_minimal() 

followers_tbl %>%
    summarise_by_time(
    .date_var = date,
    .by = "month",
    `Cumulative Followers` = sum(new_followers)
  ) %>%
  mutate(
    `Cumulative Followers` = cumsum(`Cumulative Followers`)
  ) %>%
  slice(1:12) %>%
  ggplot(aes(x = date, y = `Cumulative Followers`)) +
  geom_col() +
  labs(
    x = "Date",
    y = "Value",
    title = "LinkedIn Stats Time Series Plot - New Followers"
  ) +
  theme_minimal() 

It seems again that writing blog posts and sharing them daily has a nice effect. Now we are going to look at some Value, Velocity, and Acceleration plots with the ts_vva_plot() function from the {healthyR.ts} package.

ts_vva_plot(engagement_tbl, date, engagements)$plots$static_plot

ts_vva_plot(engagement_tbl, date, impressions)$plots$static_plot

ts_vva_plot(engagement_tbl, date, `Engagement Rate`)$plots$static_plot

ts_vva_plot(followers_tbl, date, new_followers)$plots$static_plot

Now some simple moving average plots using the function ts_sma_plot() again from the {healthyR.ts} library.

ts_sma_plot(engagement_tbl, date, impressions, .sma_order = c(7, 14, 21, 30))$plots$static_plot

ts_sma_plot(engagement_tbl, date, engagements, .sma_order = c(7, 14, 21, 30))$plots$static_plot

ts_sma_plot(engagement_tbl, date, `Engagement Rate`, .sma_order = c(7, 14, 21, 30))$plots$static_plot

ts_sma_plot(followers_tbl, date, new_followers, .sma_order = c(7, 14, 21, 30))$plots$static_plot

Now some calendar heatmaps with ts_calendar_heatmap_plot()

ts_calendar_heatmap_plot(engagement_tbl, date, impressions, .interactive = FALSE) +
  labs(title = "Calendar Heatmap - Impressions")

ts_calendar_heatmap_plot(engagement_tbl, date, engagements, .interactive = FALSE) +
  labs(title = "Calendar Heatmap - Engagemets")

ts_calendar_heatmap_plot(engagement_tbl, date, `Engagement Rate`, .interactive = FALSE) +
  labs(title = "Calendar Heatmap - Engagement Rate")

ts_calendar_heatmap_plot(followers_tbl, date, new_followers, .interactive = FALSE) +
  labs(title = "Calendar Heatmap - New Followers")

Some seasonal diagnostics using {timetk}

plot_seasonal_diagnostics(engagement_tbl
                          , date, engagements, .interactive = FALSE,
                          .feature_set = c("wday.lbl", "month.lbl"),
                          .title = "Seasonal Diagnostics - Engagements") +
  theme_minimal()

plot_seasonal_diagnostics(engagement_tbl
                          , date, impressions, .interactive = FALSE,
                          .feature_set = c("wday.lbl", "month.lbl"),
                          .title = "Seasonal Diagnostics - Impressions") +
  theme_minimal()

plot_seasonal_diagnostics(engagement_tbl
                          , date, `Engagement Rate`, .interactive = FALSE,
                          .feature_set = c("wday.lbl", "month.lbl"),
                          .title = "Seasonal Diagnostics - Engagement Rate") +
  theme_minimal()

plot_seasonal_diagnostics(
  followers_tbl, date, new_followers, .interactive = FALSE, 
  .feature_set = c("wday.lbl","month.lbl"), 
  .title = "Seasonal Diagnostics - New Followers") +
  theme_minimal()

Finally some lag correlation plots with ts_lag_correlation().

ts_lag_correlation(engagement_tbl, date, engagements, .lags = c(7, 14, 21, 28))$plots$lag_plot +
  labs(title = "Lag Correlation Plot - Engagements") +
  geom_smooth(se = FALSE, method = "lm", color = "black", linetype = "dashed")

ts_lag_correlation(engagement_tbl, date, impressions, .lags = c(7, 14, 21, 28))$plots$lag_plot +
  labs(title = "Lag Correlation Plot - Impressions") +
  geom_smooth(se = FALSE, method = "lm", color = "black", linetype = "dashed")

ts_lag_correlation(engagement_tbl, date, `Engagement Rate`, .lags = c(7, 14, 21, 28))$plots$lag_plot +
  labs(title = "Lag Correlation Plot - Engagement Rate") +
  geom_smooth(se = FALSE, method = "lm", color = "black", linetype = "dashed")

ts_lag_correlation(followers_tbl, date, new_followers, .lags = c(7, 14, 21, 28))$plots$lag_plot +
  labs(title = "Lag Correlation Plot - New Followers") +
  geom_smooth(se = FALSE, method = "lm", color = "black", linetype = "dashed")

Key Stats and Tables

Now we are going to look at some key stats and tables. First we will look at the top 10 posts by impressions.

top_posts_tbl %>%
  select(post_publish_date_2, impressions, post_url_1) %>%
  arrange(desc(impressions)) %>%
  head(10) %>%
  setNames(c("Post Date", "Impressions", "Post URL")) %>%
  kable(caption = "Top 10 Posts by Impressions", align = "c")
Top 10 Posts by Impressions
Post Date Impressions Post URL
2/16/2023 43951 https://www.linkedin.com/feed/update/urn:li:activity:7031977309351890944
2/16/2023 38656 https://www.linkedin.com/feed/update/urn:li:activity:7031977249448820737
3/16/2023 34402 https://www.linkedin.com/feed/update/urn:li:activity:7042173970149728257
1/24/2023 32505 https://www.linkedin.com/feed/update/urn:li:activity:7023663053699207168
8/24/2023 25205 https://www.linkedin.com/feed/update/urn:li:activity:7100535469263699968
1/17/2023 24916 https://www.linkedin.com/feed/update/urn:li:activity:7021114787371614209
1/5/2023 22656 https://www.linkedin.com/feed/update/urn:li:activity:7016769698595749888
3/10/2023 21943 https://www.linkedin.com/feed/update/urn:li:activity:7039960379266883585
6/23/2023 20559 https://www.linkedin.com/feed/update/urn:li:activity:7078000250656808960
2/21/2023 19730 https://www.linkedin.com/feed/update/urn:li:activity:7033888693216018432

Now we will look at the top 10 posts by engagements.

top_posts_tbl %>%
  select(post_publish_date_2, engagements, post_url_1) %>%
  arrange(desc(engagements)) %>%
  head(10) %>%
  setNames(c("Post Date", "Engagements", "Post URL")) %>%
  kable(caption = "Top 10 Posts by Engagements", align = "c")
Top 10 Posts by Engagements
Post Date Engagements Post URL
2/16/2023 281 https://www.linkedin.com/feed/update/urn:li:activity:7031977309351890944
2/16/2023 227 https://www.linkedin.com/feed/update/urn:li:activity:7031977249448820737
3/16/2023 220 https://www.linkedin.com/feed/update/urn:li:activity:7042173970149728257
1/24/2023 194 https://www.linkedin.com/feed/update/urn:li:activity:7023663053699207168
8/24/2023 181 https://www.linkedin.com/feed/update/urn:li:activity:7100535469263699968
1/17/2023 172 https://www.linkedin.com/feed/update/urn:li:activity:7021114787371614209
1/5/2023 160 https://www.linkedin.com/feed/update/urn:li:activity:7016769698595749888
3/10/2023 145 https://www.linkedin.com/feed/update/urn:li:activity:7039960379266883585
6/23/2023 138 https://www.linkedin.com/feed/update/urn:li:activity:7078000250656808960
2/21/2023 124 https://www.linkedin.com/feed/update/urn:li:activity:7033888693216018432

Now we will look at the top 10 posts by engagement rate.

top_posts_tbl %>%
  select(post_publish_date_2, engagements, impressions, post_url_1) %>%
  mutate(engagement_rate = engagements / impressions) %>%
  arrange(desc(engagement_rate)) %>%
  select(post_publish_date_2, engagement_rate, post_url_1) %>%
  head(10) %>%
  setNames(c("Post Date", "Engagement Rate", "Post URL")) %>%
  kable(caption = "Top 10 Posts by Engagement Rate", align = "c")
Top 10 Posts by Engagement Rate
Post Date Engagement Rate Post URL
8/24/2023 0.0071811 https://www.linkedin.com/feed/update/urn:li:activity:7100535469263699968
1/5/2023 0.0070621 https://www.linkedin.com/feed/update/urn:li:activity:7016769698595749888
1/17/2023 0.0069032 https://www.linkedin.com/feed/update/urn:li:activity:7021114787371614209
5/10/2023 0.0068692 https://www.linkedin.com/feed/update/urn:li:activity:7062043144850137088
2/6/2023 0.0067925 https://www.linkedin.com/feed/update/urn:li:activity:7028379188441010176
7/17/2023 0.0067441 https://www.linkedin.com/feed/update/urn:li:activity:7086688278245961728
11/29/2023 0.0067365 https://www.linkedin.com/feed/update/urn:li:activity:7135620032557940736
6/23/2023 0.0067124 https://www.linkedin.com/feed/update/urn:li:activity:7078000250656808960
1/25/2023 0.0066225 https://www.linkedin.com/feed/update/urn:li:activity:7024095415348133889
3/10/2023 0.0066080 https://www.linkedin.com/feed/update/urn:li:activity:7039960379266883585

Total Impressions: 2,720,605

Total Engagements: 20,000

Mean Engagement Rate: 0.0073513

New Followers: 6,388

And finally the demographics of people who typically interact with my posts:

demographics_tbl %>%
  mutate(percentage = substr(percentage, 1, 4)) %>%
  kable(
    caption = "Demographics of People Who Interact With My Posts", 
    align = "c"
    )
Demographics of People Who Interact With My Posts
top_demographics value percentage
Job titles Data Scientist 0.05
Job titles Data Analyst 0.03
Job titles Software Engineer 0.02
Job titles Data Engineer 0.01
Job titles Professor 0.01
Locations New York City Metropolitan Area 0.06
Locations Greater Bengaluru Area 0.03
Locations Greater Delhi Area 0.02
Locations Pune/Pimpri-Chinchwad Area 0.02
Locations Mumbai Metropolitan Region 0.01
Industries IT Services and IT Consulting 0.22
Industries Software Development 0.11
Industries Higher Education 0.05
Industries Financial Services 0.05
Industries Hospitals and Health Care 0.05
Seniority Senior 0.33
Seniority Entry 0.27
Seniority Director 0.03
Seniority Manager 0.03
Seniority Training 0.02
Company size 10,001+ employees 0.17
Company size 1001-5000 employees 0.10
Company size 51-200 employees 0.08
Company size 11-50 employees 0.08
Company size 1-10 employees 0.06
Companies Tata Consultancy Services < 1%
Companies Long Island Community Hospital < 1%
Companies Amazon < 1%
Companies EY < 1%
Companies Citi < 1%

Voila!