Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Time Series Analysis of Plausible Data
Blacknight318
Blacknight318

Posted on • Originally published atsaltyoldgeek.com

Time Series Analysis of Plausible Data

Purpose of the notebook

Early on with this blog I wanted a way to track its usage, just to see if anyone was reading it, and it needed to be GDPR compliant. EnterPlausible Analytics, it was GDPR compliant without needing the cookie or consent banners. This is great for simple metrics, especially for a small blog or site. Now, after a year of usage, there are a few features that would be nice to have. As of this writing the bounce rate is calculated by how many users navigate to another page on the site, this is something I'll be working on and sending out an updated post on that. This post will go over using the Plausible API to perform some time series analysis on data from Plausible. this will focus on visitors and pageviews. Let's dive in.

Prerequisites

To get things started let's set up a Python virtual environment and Jupyter Labs to work with our data. The following commands will do both.

mkdirplausiblecdplausiblepython3-m venv venvsourcevenv/bin/activatepipinstall--upgrade pippipinstall--upgrade jupyterlab ipywidgets
Enter fullscreen modeExit fullscreen mode

Libraries and Pulling Data

Now that we have a working environment we'll get the libraries installed that we'll need along with a function that pulls data from plausible into a dataframe we can use.

Libraries

Below is the code for the libraries we're going to use in this project, keep in mind that these are all the libraries for the final project.

importrequestsimportpandasaspdfromdatetimeimportdatetime,timedeltaimportplotly.expressaspximportplotly.graph_objectsasgofromplotly.subplotsimportmake_subplotsfromstatsmodels.tsa.seasonalimportseasonal_decompose
Enter fullscreen modeExit fullscreen mode

We can install these libraries using pip with the following command.

pipinstall--upgrade pandas plotly statsmodels
Enter fullscreen modeExit fullscreen mode

Pulling Data from Plausible

We'll want to set a few keys/variables up for use when pulling the data.

site_id="Your Plausible Site ID Here"api_key="Your Plausible API Key Here"
Enter fullscreen modeExit fullscreen mode

Now we'll want to pull data for our site from Plausible API, you'll want to go to Account Settings in Plausible and scroll down to API Keys, then generate a key to work with, we'll also want the Site ID which is the domain listed in the site settings. Ok, let's build this function.

# Function to get Plausible Analytics timeseries datadefget_plausible_timeseries_data():# Calculate the date range for the last 90 daysdate_to=datetime.today().strftime('%Y-%m-%d')date_from=(datetime.today()-timedelta(days=90)).strftime('%Y-%m-%d')# Setting the metrics we want to look atmetrics='visitors,pageviews'# Actually pulling the data we wanturl=f"https://plausible.io/api/v1/stats/timeseries?site_id={site_id}&period=custom&date={date_from},{date_to}&metrics={metrics}"headers={"Authorization":f"Bearer{api_key}"}response=requests.get(url,headers=headers)data=response.json()# Putting the data into a dataframe we can use for analysisresults=data['results']df=pd.DataFrame(results)# Adjusting the date field so we can avoid future warnings and be more accuratedf['date']=pd.to_datetime(df['date'])returndf
Enter fullscreen modeExit fullscreen mode

Data Analysis

Now that we have the data let's perform some analysis, looking for patterns/seasonality, and graph it out for easier consumption.

Seasonal Decomposition

While building this tool I had considered using code from an earlier project that leveraged Prophet and/or Neuralprohet engines, but after putting the data through 2 different AIs (ChatGPT 4o and Gemini 1.5) to get a quick analysis, I ended up going with the same process that ChatGPT 4o used, seasonal decomposition. There was a bit of tweaking to do to the original code to get it to work in the environment we're going to use, and changing the plots to Plotly from Matplotlib for more interactive data. Here's the end result code for performing the analysis.

# Function to perform seasonal decompositiondefplot_seasonal_decomposition(df,column,period=7):decomposition=seasonal_decompose(df[column],model='additive',period=period)fig=make_subplots(rows=4,cols=1,shared_xaxes=True,subplot_titles=('Observed','Trend','Seasonal','Residual'))fig.add_trace(go.Scatter(x=decomposition.observed.index,y=decomposition.observed,name='Observed'),row=1,col=1)fig.add_trace(go.Scatter(x=decomposition.trend.index,y=decomposition.trend,name='Trend'),row=2,col=1)fig.add_trace(go.Scatter(x=decomposition.seasonal.index,y=decomposition.seasonal,name='Seasonal'),row=3,col=1)fig.add_trace(go.Scatter(x=decomposition.resid.index,y=decomposition.resid,name='Residual'),row=4,col=1)fig.update_layout(height=800,title_text=f'{column.capitalize()} - Seasonal Decomposition',template='plotly_dark')fig.show()
Enter fullscreen modeExit fullscreen mode

Plotting the data

Here's the Plotly code used, besides being interactive I was able to use a dark theme that doesn't hurt the eyes as much, which also took some tweaking, here's that code.

# Function to plot day of the week trendsdefplot_day_of_week_trends(df):df=df.reset_index()df['day_of_week']=df['date'].dt.day_name()day_of_week_stats=df.groupby('day_of_week').mean(numeric_only=True)[['pageviews','visitors']]days_order=['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']day_of_week_stats=day_of_week_stats.reindex(days_order)fig=go.Figure()fig.add_trace(go.Scatter(x=day_of_week_stats.index,y=day_of_week_stats['pageviews'],mode='lines+markers',name='Pageviews'))fig.add_trace(go.Scatter(x=day_of_week_stats.index,y=day_of_week_stats['visitors'],mode='lines+markers',name='Visitors'))fig.update_layout(title='Average Pageviews and Visitors by Day of the Week',xaxis_title='Day of the Week',yaxis_title='Count',template='plotly_dark')fig.show()
Enter fullscreen modeExit fullscreen mode

Main Code and Running

Now we'll create a main function, this isn't strictly necessary but it's good practice especially if you might be using it as a class in the future. Let's take a look.

# Main function to load data and perform analysisdefmain():df=get_plausible_timeseries_data()df.set_index('date',inplace=True)# Seasonal decomposition for pageviews and visitorsplot_seasonal_decomposition(df,'pageviews')plot_seasonal_decomposition(df,'visitors')# Day of week trendsplot_day_of_week_trends(df)
Enter fullscreen modeExit fullscreen mode

We then run it with the following code snippet.

if__name__=="__main__":main()
Enter fullscreen modeExit fullscreen mode

It Lives

Once you have the code in your notebook be sure that you run all the cells(if you have them split up) and you should get several graphs.

  • Pageviews - Seasonal Decomposition
  • Visitors - Seasonal Decomposition
  • Average Pageviews and Visitors by Day of the Week

That last graph has been the most useful so far, giving me metrics by day of the week to find the best time to release new posts. In a future post, I hope to look into the script Plausible uses to collect metrics and see if we can add a check the timer and drop any that are on the page for more than 10 seconds from the bounce rate numbers(this is how Google Analytics and Posthog calculate bounce rate). That's a topic for another time. Till next time, fair winds and following seas.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Sysadmin, Network tech, helpdesk, and Security, with a pinch of Powershell experience
  • Location
    La Crosse, WI
  • Work
    Computer Tech II at School District
  • Joined

More fromBlacknight318

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp