Social Media Campaign Assignment

Author

Kayla Nolan

library(tidyverse)
#install.packages("janitor") 
#install.packages("furniture") 
library(janitor)
library(furniture)
#install.packages("kableExtra")
library(kableExtra)


social <- read_csv("social_media_campaign_data.csv")

1 Introduction

Today we will be exploring and analyzing social media campaigns that were ran by a company, The data contains the following variables for 942 social media campaigns

  • Campaign ID
  • Campaign
  • Post Date
  • Post Hour
  • Boosted Post
  • Spend
  • Content Theme
  • Platform
  • Post Type
  • Target Age
  • Target Group
  • Emoji Count
  • Hash Tag Count
  • Word Count
  • Impressions
  • Reach
  • Engagements
  • Clicks
  • Conversions
  • Conversion Value
  • CTR

In this report, we will look at different variables of the data to understand how the company’s social media performance varies across platforms, post types, target groups, and time periods. The goal of the analysis is to identify what types of posts perform best, which audiences are the most valuable, and how spending relates to conversions and engagement. By exploring these patterns, we can give the business useful insights that can help improve future campaigns and make more effective marketing decisions.

social_clean <- social %>%
  remove_empty("rows") %>%            
  remove_empty("cols") %>%
  clean_names()

2 Exploring Campaign Spend vs Conversions using Content Themes.

ggplot(data = social_clean) +
  geom_point(mapping = aes(x = spend, y = conversions, colour = content_theme) ,size = 0.5) +
  scale_colour_manual(values = c("cyan2","darkviolet","deeppink","darkorange1","red2" )) +
  ggtitle("Overall Campaign Spend vs. Conversions
          by Content Theme") +
  facet_wrap(~ content_theme, nrow = 2) +    # Separate panel for each theme
  theme(legend.position = "none")            # Hides legend

The Scatter plot above shows how spend relates to conversions for each content theme in the campaign. Each theme has its own graphic, which makes it easier to compare. Overall, we can see that when spend increases, conversions also increase although pattern looks different for each theme. Some themes like Lifestyle and Behind-the-Scenes have a wide range of conversions even at similar spend levels, meaning the results are less predictable. While Promotion and User Testimonial have points that are closer grouped which shows more consistent performance. This graph helps see which content themes are giving better conversions for the amount spent and can be useful when deciding where to focus future spending for the business.

3 Average Engagement by Post Type.

avg_engagement <- social_clean %>%
  group_by(post_type) %>%  
  summarise(avg_engagement = mean(engagements, na.rm = TRUE)) %>%
  mutate(avg_engagement2 = floor(avg_engagement))    # Rounds down the tables
  
  
  
ggplot(data = avg_engagement) +
  geom_col(mapping = aes(x = reorder(post_type, -avg_engagement), y = avg_engagement, fill = post_type)) +
  scale_fill_manual(values = c("cyan2","darkviolet","deeppink","darkorange1","red2" )) +
    theme(legend.position = "none") +
    ggtitle("Average Engagement by Post Type") +
  xlab("Post Type") +
  ylab("Avg Engagement") +
   geom_text(aes(x = reorder(post_type, -avg_engagement), y = (avg_engagement), 
              label = avg_engagement2), vjust = 1, colour = "white")    # adds white labels on the bars

This Barchart shows the Average engagement by post type.We can see that Story posts had the highest engagement overall, followed closely by Carousel posts. Reels and Video also performed well but slightly lower and Image posts received the least engagement. Overall, the chart suggests that more interactive post types like Stories, Carousels, and Reels tend to get higher engagement, while static images receive the lowest. This can help when deciding which post types the business should focus on to maximise engagement.

4 Engagement Levels based on Social Media Platforms.

ggplot(data = social_clean) +
  geom_boxplot(mapping = aes(x = platform, y = engagements, fill = platform), outlier.shape = 5, outlier.colour = "blue") +
  scale_fill_manual(values = c("cyan2","darkviolet","deeppink","darkorange1" )) +
  theme(legend.position = "none") +
   ggtitle("Engagement VS Platform")

This Box Plot shows the engagement levels based on each platform. Each platform has a similar overall range but there are a few differences. Instagram has lower engagement compared to the others, while LinkedIn and TikTok show slightly higher median engagement levels. All platforms have several high outliers which represent posts that performed much better than average.X shows the widest spread of engagement which means its performance varies a lot from post to post.

Overall this graph shows that engagement can be unpredictable across all platforms, but some platforms like LinkedIn and X tend to have stronger engagement on average.Knowing how engagement is different across platforms helps the business understand where their content performs best and which platforms are worth investing more time and budget into.

5 Spend over time by Month

month_spend <- social_clean %>%
  mutate(month_year = floor_date(post_date, "month")) %>%      # Rounds dates down to first of month
  group_by(month_year) %>%
  summarise(total_spend = sum(spend, na.rm = TRUE))

ggplot(data = month_spend, aes(x = month_year, y = total_spend)) +
  geom_line(color = "cyan2", linewidth = 1) +
  geom_point(color = "darkviolet", size = 2) +
    scale_x_date(date_breaks = "1 month",date_labels = "%b %Y",expand = expansion(mult = c(0.01, 0.01))) +
  labs(x = "Month",y = "Total Spend",title = "Monthly Total Spend Over Time") +
  theme_minimal(base_size = 14) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),    # Angles the x axis for better visibility
    plot.title = element_text(face = "bold"),
    panel.grid.minor = element_blank())

This Line Graph shows the total spend over time from June 2024 to June 2025. The spending goes up and down throughout the year with noticeable peaks in December 2024 and March 2025, where the business invested the most. There are also drops such as in September 2024 and January 2025 where spending was much lower compared to other months. Overall the graph shows that the business does not spend the same amount every month and tends to increase spending around key periods likely for seasonal campaigns or major promotions.

6 Average Conversion Value By Target Group (e.g Millenials, Gen Z)

social_clean %>%
  group_by(target_group) %>%
  summarise(avg_conversion_value = mean(conversion_value, na.rm = TRUE)) %>%
  
  
  ggplot(aes(x = reorder(target_group, avg_conversion_value),y = avg_conversion_value,fill = target_group)) +
  geom_col() +
  coord_flip() +   # Makes the bars horizontal 
  scale_fill_manual(values = c("cyan2","darkviolet","deeppink","darkorange1","red2")) +
  labs(title = "Average Conversion Value by Target Group",
       x = "Target Group",
       y = "Average Conversion Value (€)") +
  theme_minimal() +
  theme(legend.position = "none")

This bar chart shows the average conversion value for each target group. From the graph, we can see that Gen X has the highest average conversion value followed closely by Gen Z. Both of these groups bring in noticeably more value per conversion compared to the others. Professionals and Parents fall in the middle, with similar conversion values and Millennials have the lowest average conversion value out of all the groups. Knowing which target groups generate the most value helps the business understand where their most profitable audience is. If certain groups consistently produce higher conversion value the business may want to focus more marketing efforts on them.

7 Seeing the relationship between Hashtags and Emojis with Engagement levels

engage_hashtag_emoji <- social_clean %>%
  pivot_longer(cols = c(hashtag_count, emoji_count),
    names_to  = "type",
    values_to = "count")

ggplot(engage_hashtag_emoji, aes(x = count, y = engagements, colour = type)) +
  geom_point(size = 2) +
  geom_smooth(method = "lm", se = FALSE) +     # adds linear trend line
  scale_color_manual( values = c(hashtag_count = "darkviolet",emoji_count   = "deeppink"),
    labels = c("Hashtags", "Emojis"),name   = "Items") +
  labs(title = "Hashtags and Emojis vs Engagements",
    x     = "Number of Hashtags / Emojis",
    y     = "Engagements") +
  theme_minimal()

This scatter plot shows the relationship between the number of hashtags and emojis used in a post and the amount of engagement it receives. Each dot represents a post and the lines show the general trend for each item. From the graph we can see that adding more hashtags or emojis does not lead to a big increase in engagement. Both trend lines are almost flat meaning there is little to no relationship between how many hashtags or emojis are used and how well a post performs.

There are still some posts with high engagement but these are spread across different hashtag and emoji counts, so they are likely influenced by other factors.This shows the business that adding hashtags or emojis won’t automatically improve engagement so they don’t need to focus too much on these.

8 Distribution of Click-Through Rates (CTR) across all campaigns.

ggplot(data = social_clean, aes(x = ctr )) +
  geom_histogram(binwidth = 0.005, fill = "darkorange1", color = "white", alpha = 0.8) +
  labs(title = "Distribution of Click-Through Rate (CTR)",
       x = "Click-Through Rate",
       y = "Number of Campaigns") +
  theme_minimal()

This histogram shows the distribution of Click-Through Rates (CTR) across all campaigns. Most campaigns have a CTR between 0.01 and 0.03, meaning this is the most common performance range. Fewer campaigns achieve very high CTRs and only a small number go above 0.05 which suggests that extremely high CTRs are quite rare. The graph has a right-skewed shape, showing that while high CTRs do happen, they are unusual compared to the majority of campaigns. Understanding the typical CTR range helps the business know what a “normal” campaign performance looks like.

9 Top 10 Campaigns by Conversion Value

top_campaigns <- social_clean %>%
  group_by(campaign) %>%
  summarise(total_value = sum(conversion_value, na.rm = TRUE),
    total_conversions = sum(conversions, na.rm = TRUE),
    total_engagements = sum(engagements, na.rm = TRUE)) %>%
  arrange(desc(total_value)) %>%    # sort by highest value
  slice_head(n = 10)                # Keep only top 10


top_campaigns %>%
  mutate(total_value = round(total_value, 2),              # Round to 2 decimal places  
    total_conversions = round(total_conversions, 0),       # Round to 0 decimal places
    total_engagements = round(total_engagements, 0)) %>%
  kable(caption = "Top 10 Campaigns by Total Conversion Value",
    col.names = c("Campaign", "Total Value (€)", "Total Conversions", "Total Engagements"),
    align = "lccc") %>%              # Aligns columns left center center center 
  kable_styling( full_width = FALSE,position = "center", bootstrap_options = c("striped", "hover")) %>%
  row_spec(0, bold = TRUE, background = "cyan2",color = "black") %>%
  row_spec(1:nrow(top_campaigns),background = "white") %>%  
  column_spec(2, color = "darkviolet") %>%  
  column_spec(3, color = "darkorange1") %>%   
  column_spec(4, color = "red2")     
Top 10 Campaigns by Total Conversion Value
Campaign Total Value (€) Total Conversions Total Engagements
Holiday 2024 251464.9 2820 49149
Back to School 2024 248982.6 2875 45249
Fall 2024 215409.4 2933 46822
Summer 2024 203331.7 2315 38030
Holiday 2025 193330.1 2377 36950
Fall 2025 169007.7 2113 33451
Spring 2025 150261.5 2063 33620
Summer 2025 149250.8 1864 29961
Spring 2024 147737.7 2270 36152
Back to School 2025 133503.5 2086 33724

This table shows the Top 10 campaigns ranked by total conversion value. From the table, we can see that Holiday 2024 generated the highest total conversion value followed closely by Back to School 2024 and Fall 2024. These campaigns also have some of the highest engagement and conversion counts showing that they performed well across multiple metrics. Campaigns such as Summer 2025 and Spring 2024 appear lower on the list, meaning they brought in less overall value compared to the top seasonal campaigns. This table helps the business identify which campaigns were the most successful and delivered the biggest return. By seeing which campaigns consistently generate high conversion value the business can learn what works well and use those insights when planning future campaigns

10 Conclusion

In summary this analysis shows what types of posts, platforms, and audiences perform best for the company. Story and Carousel posts had the highest engagement and Gen X and Gen Z brought in the most conversion value. Spending also changed across the year with bigger peaks during seasonal campaigns. We also found that hashtags and emojis did not have much impact on engagement. Overall these insights can help the business focus on the most effective content and audiences to improve future social media campaigns.

Struggles of Rstudio