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")Social Media Campaign Assignment
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 legendThe 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 barsThis 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.
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.
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") | 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.