import pandas as pd
import numpy as np
import plotly.express as px
import plotly.io as pio
import plotly.graph_objects as go
# this formats numbers to two decimal places when shown in pandas
pd.set_option('display.float_format', lambda x: '%.2f' % x)
# sets the default theme
pio.templates["webpage_bg"] = go.layout.Template(
layout={
"font": {"color": "#ffffff"},
"paper_bgcolor": "#222222"
}
)
pio.templates.default = "ggplot2+webpage_bg"
full_df = pd.read_csv('datasets_grammys/grammy_live_web_analytics.csv')
rec_academy = pd.read_csv('datasets_grammys/ra_live_web_analytics.csv')Grammys Project
In this project, I will be analyzing real data from both websites owned by The Recording Academy, the non-profit organization behind the famous Grammy Awards. Ray Starck, the VP of Digital Strategy, decided to split the websites into grammy.com and recordingacademy.com to better serve the Recording Academy’s various audience needs. My goal is to determine how the decision to split these 2 websites impacted overall traffic and audience behavior to the websites.
Data Dictionary
To start, I have these two files, grammy_live_web_analytics.csv and ra_live_web_analytics.csv.
These files contain the following information:
- date - The date the data was confirmed. It is in
yyyy-mm-ddformat. - visitors - The number of users who went on the website on that day.
- pageviews - The number of pages that all users viewed on the website.
- sessions - The total number of sessions on the website. A session is a group of user interactions with your website that take place within a given time frame. For example a single session can contain multiple page views, events, social interactions.
- bounced_sessions - The total number of bounced sessions on the website. A bounced session is when a visitor comes to the website and does not interact with any pages / links and leaves.
- avg_session_duration_secs - The average length for all session durations for all users that came to the website that day.
- awards_week - A binary flag if the dates align with marketing campaigns before and after the Grammys award ceremony was held. This is the big marketing push to get as many eyeballs watching the event.
- awards_night - The actual night that the Grammy Awards event was held.
Part I - Exploratory Data Analysis
Code
full_df.sample(5)| date | visitors | pageviews | sessions | bounced_sessions | avg_session_duration_secs | awards_week | awards_night | |
|---|---|---|---|---|---|---|---|---|
| 37 | 2017-02-07 | 47583 | 122424 | 52246 | 31531 | 108 | 1 | 0 |
| 117 | 2017-04-28 | 7011 | 13079 | 7342 | 5301 | 69 | 0 | 0 |
| 1610 | 2021-05-30 | 34487 | 58234 | 36626 | 13849 | 90 | 0 | 0 |
| 392 | 2018-01-28 | 1609729 | 5446407 | 1934941 | 612022 | 221 | 1 | 0 |
| 949 | 2019-08-08 | 14950 | 20165 | 15679 | 7302 | 81 | 0 | 0 |
Code
rec_academy.sample(5)| date | visitors | pageviews | sessions | bounced_sessions | avg_session_duration_secs | awards_week | awards_night | |
|---|---|---|---|---|---|---|---|---|
| 74 | 2022-04-16 | 665 | 1375 | 753 | 529 | 80 | 0 | 0 |
| 277 | 2022-11-05 | 883 | 3151 | 1029 | 49 | 111 | 0 | 0 |
| 184 | 2022-08-04 | 1328 | 2621 | 1595 | 1143 | 85 | 0 | 0 |
| 347 | 2023-01-14 | 1284 | 4952 | 1577 | 326 | 120 | 0 | 0 |
| 306 | 2022-12-04 | 1236 | 5126 | 1442 | 207 | 117 | 0 | 0 |
We all know The Grammy Awards is the biggest music event in the music industry, but how many visitors does that bring to the website?
Code
px.line(data_frame=full_df,
x='date',
y='visitors',
title='Number of Visitors to the Grammy\'s Website Over Time')The smaller spikes, typically around November/December of each year, are when the nominees are announced.
Some observations I made:
- The number of visitors on days that are not directly related to the awards are much lower and were slowly increasing until 2022, where they stay steady.
- The spike of visitors on the days the nominees are being announced is usually less than half of the number of visitors on the awards ceremony.
- 2019 and 2021 had the highest number of visitors on their awards days
- The awards ceremony in 2021 also had the highest number of visitors on the day the nominees were announced.
- There is an unexpected spike of visitors on Sep. 2020
Let’s investigate what an “average” day looks like when the awards show is being hosted versus the other 364 days out of the year.
Code
full_df.groupby(by='awards_night').agg({'visitors': 'mean'})| visitors | |
|---|---|
| awards_night | |
| 0 | 32388.28 |
| 1 | 1389590.23 |
An awards night has on average around 1 million more visitors than the average of a regular day (around 43x more traffic on an awards night on average then a regular day on average)
This is The Recording Academy’s biggest challenge! How do you transform a business that relies on the success of one event per year into one that continues to bring users back on the site year round?
When The Recording Academy decided to split their website into two domains, grammy.com and recordingacademy.com, the data capture for grammy.com was not affected. So the full_df variable needs to be split separately into two dataframes. The day the domains were switched is on 2022-02-01.
The new dataframes for convenience:
combined_sitefor all dates before2022-02-01grammysfor all dates after (and including)2022-02-01
combined_site = full_df[full_df['date'] < '2022-02-01']
grammys = full_df[full_df['date'] >= '2022-02-01']
combined_site = combined_site.copy()
grammys = grammys.copy()Part II - It’s all about KPIs
There are certain key performance indicators (KPIs) of interest for The Recording Academy. Let’s investigate those a little more.
frames = [combined_site, rec_academy, grammys]Pages Per Session
For each frame in the frames list, we will look at pages_per_session. This is the average number of pageviews per session on a given day, which is measured as:
\(pages\_per\_session=\frac{pageviews}{sessions}\)
The higher this number the more “stickiness” your website has with your visitors.
for frame in frames:
frame['pages_per_session'] = frame['pageviews'] / frame['sessions']Let’s take a look at how these metrics compare across all 3 websites:
Code
# combined_site graph
px.line(data_frame=combined_site,
x='date',
y='pages_per_session',
title='Average Pages per Session on the Grammy\'s Combined Website Over Time')Code
# grammys graph
px.line(data_frame=grammys,
x='date',
y='pages_per_session',
title='Average Pages per Session on the Grammy\'s Website Over Time')Code
# rec_academy graph
px.line(data_frame=rec_academy,
x='date',
y='pages_per_session',
title='Average Pages per Session on the Recording Academy\'s Website Over Time')Any large spikes in the data that do not correspond with the Grammy Awards Ceremony can be attributed to abnormalities in the data collection process and ignored in this analysis.
Before the split, the number of pages per session was around 1-2 pages, but after the split, the pages per session on the grammy’s stayed around 2, and the recording academy has around 2-3 pages.
Bounce Rate
Bounce rate is another important metric for The Recording Academy. Bounce Rate is a measure of the percentage of visitors who come to the site and never interact with the website and leave. This metric is defined as:
\(bounce\_rate=\frac{\sum bounced\_sessions}{\sum sessions}\times 100\%\)
def bounce_rate(dataframe):
'''
Calculates the bounce rate for visitors on the website.
input: dataframe with bounced_sessions and sessions columns
output: numeric value from bounce rate
'''
sum_bounced = dataframe['bounced_sessions'].sum()
sum_sessions = dataframe['sessions'].sum()
return 100 * sum_bounced / sum_sessionsframe_names = ['The Combined Site', 'The Recording Academy Site', 'The Grammys Site']
for frame, name in zip(frames, frame_names):
b_rate = bounce_rate(frame)
print(f'The bounce rate of {name} is {b_rate:0.2f}%')The bounce rate of The Combined Site is 41.58%
The bounce rate of The Recording Academy Site is 33.67%
The bounce rate of The Grammys Site is 40.16%
Average Session Duration
for frame, name in zip(frames, frame_names):
avg_session_duration = frame['avg_session_duration_secs'].mean()
print(f'The average session duration on {name} is {avg_session_duration:.2f} sec.')The average session duration on The Combined Site is 102.85 sec.
The average session duration on The Recording Academy Site is 128.50 sec.
The average session duration on The Grammys Site is 82.99 sec.
Some observations I made on these 2 new metrics:
The recording academy has the lowest bounce rate and the longest average session duration. The combined site had the highest bounce rate and the grammys site had the lowest session rate. Based on the values for the bounce rate and average session duration, it looks like splitting the combined site lead the stickier users (users that don’t bounce as much) that have longer session times to the recording academy site, and the less sticky users to the grammys site.
Part III - Demographics
Age demographics are a way to see which audience(s) your content is resonating with the most. This can inform marketing campaigns, ads, and much more.
Let’s investigate the demographics for the two websites.
The grammys_age_demographics.csv and tra_age_demographics.csv each contain the following information:
- age_group - The age group range. e.g.
18-24are all visitors between the ages of 18 to 24 who come to the site. - pct_visitors - The percentage of all of the websites visitors that come from that specific age group.
age_grammys = pd.read_csv('datasets_grammys/grammys_age_demographics.csv')
age_tra = pd.read_csv('datasets_grammys/tra_age_demographics.csv')Code
display(age_grammys)| age_group | pct_visitors | |
|---|---|---|
| 0 | 18-24 | 27.37 |
| 1 | 25-34 | 24.13 |
| 2 | 35-44 | 18.72 |
| 3 | 45-54 | 13.57 |
| 4 | 55-64 | 9.82 |
| 5 | 65+ | 6.39 |
age_grammys['website'] = 'Grammys'
age_tra['website'] = 'Recording Academy'
age_dif = pd.concat([age_grammys, age_tra], join='inner')Code
px.bar(age_dif,
x='age_group',
y='pct_visitors',
color='website',
barmode='group',
title='Demographic Breakdown of Visitors by Percentage to the Split Websites')The age demographics for both websites is almost identical, but the recording academy has a slightly higher percentage of users 25-34 years old and the grammys has a slightly higher percentage of users 55+ years old.
Part IV - Recommendation
for frame, name in zip(frames, frame_names):
print(f'{name} pages per session:')
print(f" mean: {frame['pages_per_session'].mean():.3f}")
print(f" median: {frame['pages_per_session'].median():.3f}")The Combined Site pages per session:
mean: 1.589
median: 1.573
The Recording Academy Site pages per session:
mean: 2.783
median: 2.885
The Grammys Site pages per session:
mean: 2.138
median: 2.104
print('On an awards week:')
for frame, name in zip(frames, frame_names):
print(f'{name} average visitors:')
print(f" mean: {frame[frame['awards_week'] == 1]['visitors'].mean():,.3f}")
print(f" median: {frame[frame['awards_week'] == 1]['visitors'].median():,.3f}")
print('----------------------------')
print('Not on an awards week:')
for frame, name in zip(frames, frame_names):
print(f'{name} average visitors:')
print(f" mean: {frame[frame['awards_week'] == 0]['visitors'].mean():,.3f}")
print(f" median: {frame[frame['awards_week'] == 0]['visitors'].median():,.3f}")On an awards week:
The Combined Site average visitors:
mean: 487,487.725
median: 192,235.000
The Recording Academy Site average visitors:
mean: 17,678.143
median: 8,483.500
The Grammys Site average visitors:
mean: 425,980.962
median: 127,669.500
----------------------------
Not on an awards week:
The Combined Site average visitors:
mean: 21,656.941
median: 16,372.000
The Recording Academy Site average visitors:
mean: 1,570.813
median: 1,279.000
The Grammys Site average visitors:
mean: 21,922.009
median: 18,079.000
Code
px.line(data_frame=combined_site,
x='date',
y='visitors',
title='Number of Visitors to the Combined Site Over Time')Code
px.line(data_frame=grammys,
x='date',
y='visitors',
title='Number of Visitors to the Grammy\'s Separated Site Over Time')Code
px.line(data_frame=rec_academy,
x='date',
y='visitors',
title='Number of Visitors to the Recording Academy\'s Website Over Time')KPI Summary
| Website | Average Pages Per Session | Bounce Rate | Average Session Duration |
|---|---|---|---|
| Combined | 1.589 | 41.58% | 102.85 sec. |
| Recording Academy | 2.783 | 33.67% | 128.50 sec. |
| Grammys | 2.138 | 40.16% | 82.99 sec. |
Based on the analysis I have done on the website data above, I would recommend the website stays separate. One of the metrics that improved since the split is the pages per view. When looking at the average pages per view, we can see that the combined site has less average pages per view then both of the separated websites. When looking at this average over time, it stays relatively consistent, with no major permanent changes other than when they split.
Another important metric is the average number of visitors to each site, during or outside of the awards week. During the awards week, the average number of visitors to the combined site is higher than the average of visitors to either of the separated sites. Outside of the awards week, the combined site has a similar average number of visitors as the the grammys website and the recording academy has a good number of visitors as well. With the averages of the grammys and recording academy combined, they have more average visitors than the combined site.
Part V - Benchmarking Against the AMA
To put the Grammys site in context, I compared it to its main competitor, the American Music Awards (AMA), using aggregated AMA data for April–June 2023 from the dashboard below.

The Total Visits column is the total number of visitors on the website during the time-span given. The Device Distribution is the percentage share of visitors coming from Desktop users (PCs, Macs, etc.) and Mobile Users (iPhone, Android, etc.).
Visitors on the AMA website are spending, on average, 5 mins and 53 seconds on the site and viewing 2.74 pages per visit (aka session). They have a bounce rate of 54.31%
The desktop_users.csv and mobile_users.csv files contain the users coming from desktop users and mobile users respectively.
desktop_users = pd.read_csv('datasets_grammys/desktop_users.csv')
mobile_users = pd.read_csv('datasets_grammys/mobile_users.csv')Code
desktop_users.sample(5)| date | segment | visitors | |
|---|---|---|---|
| 8 | 2022-02-09 | Desktop Traffic | 10404 |
| 252 | 2022-10-11 | Desktop Traffic | 8396 |
| 403 | 2023-03-11 | Desktop Traffic | 4094 |
| 425 | 2023-04-02 | Desktop Traffic | 2295 |
| 13 | 2022-02-14 | Desktop Traffic | 7197 |
Code
mobile_users.sample(5)| date | segment | visitors | |
|---|---|---|---|
| 44 | 2022-03-17 | Mobile Traffic | 15384 |
| 297 | 2022-11-25 | Mobile Traffic | 18957 |
| 196 | 2022-08-16 | Mobile Traffic | 10143 |
| 239 | 2022-09-28 | Mobile Traffic | 10899 |
| 361 | 2023-01-28 | Mobile Traffic | 33481 |
To use this data, I want to combine both datasets and rename some columns to make it easier to combine them.
desktop_users.rename(columns={'visitors': 'desktop_visitors'}, inplace=True)
mobile_users.rename(columns={'visitors': 'mobile_users'}, inplace=True)
desktop_users.drop('segment', axis=1, inplace=True)
mobile_users.drop('segment', axis=1, inplace=True)
segment_df = pd.merge(left=desktop_users,
right=mobile_users,
on='date')Now that we have combined the datasets together, let’s look at the percentage share of users coming from desktop and mobile on the Grammys website.
segment_df['total_visitors'] = segment_df['desktop_visitors'] + segment_df['mobile_users']To calculate the percentage share we will need to filter the data to dates after (and including) 2023-04-01.
filtered_seg_df = segment_df[segment_df['date'] >= '2023-04-01']
total_visitors = filtered_seg_df['total_visitors'].sum()
perc_desktop_visitors = filtered_seg_df['desktop_visitors'].sum() / total_visitors * 100
perc_mobile_users = filtered_seg_df['mobile_users'].sum() / total_visitors * 100
print(f'Total visitors: {total_visitors:,} visitors')
print(f'Desktop users: {perc_desktop_visitors:.2f}%')
print(f'Mobile users: {perc_mobile_users:.2f}%')Total visitors: 1,428,482 visitors
Desktop users: 31.84%
Mobile users: 68.16%
Now that we have all of our metrics calculated, let’s compare both websites to see where the Grammys are doing well and where they need to improve.
| Website | Bounce Rate | Total Visits | % Desktop Users | % Mobile Users | Average Session Length (sec) | Average Pages per Visit |
|---|---|---|---|---|---|---|
| Grammys | 40.16% | 1.4 million | 32% | 68% | 83 | 2.138 |
| AMA | 54.31% | 37 thousand | 13% | 87% | 353 | 2.74 |
The Grammy’s website is doing better than its competitor in bounce rates, total visits and device distribution. The bounce rate for the grammy’s site is around 15% less than AMA’s site. The Grammy’s site also has over 1 million more users than AMA’s site.
The Grammy’s site is falling behind AMA in pages per visit and average seconds per session. AMA has 270 sec. more per session on average. AMA also has 0.6 pages per visit over the grammy’s site.