I Built a Reusable Dashboard for Read the Docs Traffic Analytics Using Vizro-AI
This article explores a simple, low code, and open-source solution to build a dashboard to visualize traffic data for documentation.
Join the DZone community and get the full member experience.
Join For FreeIn this article, I'll explain how I built a dashboard to visualize the traffic data for some documentation I maintain as a technical writer. I have few design skills and limited Python experience, so I needed a simple, low-code approach to show the impact and usage of the documentation I maintain. This turned out to be an open-source solution: Vizro as a template for a low-code dashboard, and Vizro-AI to build individual charts with generative AI.
TL;DR?
If you want to jump right in, you can find the Jupyter Notebook code for the dashboard in my GitHub repo.
A Read the Docs Dashboard Project
If, like me, you manage an open-source docs project with Read the Docs (RTD), you have probably discovered that you can download the last 90 days' worth of traffic data in CSV format from your project dashboard. The dashboard also displays a daily pageview totals chart, like the one below.
For additional visual output, you could harness Google Analytics (GA). However, some projects prefer not to use GA because its compliance with the General Data Protection Regulation (GDPR) is seen as controversial, particularly in the European Union (EU).
Just a note that in the example below, I've used a set of fake CSV traffic data that I generated, with help from OpenAI, to keep the traffic to our project private. The fake data has the same fields as genuine RTD data so you can download and use the dashboard with the data downloaded from your RTD dashboard.Get the Code and Data
To run through the example yourself, you'll need my fake data (or your own download) and the Jupyter Notebook code, stored in my GitHub repo. It's simple to step through at a basic level, but a more advanced user can extend it. Please let me know if you do create an enhanced version!
Vizro is a framework built on top of Plotly and Dash that uses a configuration approach to specify custom dashboard layouts. A Vizro dashboard can be populated with charts built by Vizro-AI, a package separate from Vizro that simplifies the visualization process by leaning on generative AI.
In this example, I supplied the data and natural language instructions, and Vizro-AI generated Python code and created my requested charts. This worked well for me as a writer, since I have no front-end design skills and I'm unfamiliar with Plotly, but I'm happy to phrase a suitable generative AI prompt and coax a chart from OpenAI.
Set Up Vizro-AI
Before running the Notebook code, you need to set up Vizro-AI inside a virtual environment with Python 3.9 or later. Install the package with pip install vizro_ai
.
Next, you need an API key to access OpenAI. If you don't already have an account, create one, and buy some credits to use a model since you cannot use the free version. Generate an API key and add it to your environment so the code you write in the next step can be accessed to successfully call OpenAI. There are some straightforward instructions in the OpenAI docs, and the process is also covered in the Vizro-AI LLM setup guide.
Build a Chart
At this point, you can open a Jupyter Notebook to make your first chart, or just open the Notebook from my repo to step through the code I created and load your RTD data (or the fake data I've provided) into a pandas DataFrame, named df
in the code below.
The following code shows how to submit a request to Vizro-AI to build a chart that resembles the chart in the Read the Docs project dashboard, showing views by date, but splitting the data into two traces, for the stable and latest versions of the documentation:
import vizro_ai
from vizro_ai import VizroAI
from dotenv import load_dotenv
load_dotenv()
vizro_ai = VizroAI(model="gpt-4–0613")
compare_versions_fig = vizro_ai.plot(df, "Combine rows of Views for each Date for latest and stable Version. Draw a line graph comparing Views per Date for latest and stable", explain=True)
compare_versions_fig.show()
Vizro-AI passes the natural language query, "Combine rows of Views for each Date for latest and stable Version. Draw a line graph comparing Views per Date for latest and stable," and the dataframe to the model. Note that in the example above, I've specified a GPT-4 model. Vizro-AI will default to use GPT-3.5-turbo because it offers a lower price point and higher speed for providing answers, but it does not offer the most sophisticated charting, so I opted to make an explicit request to use a GPT-4 model.
The chart output will depend on your data, and on the output received from OpenAI at the time the query was submitted. The parameter explain=True
requests that Vizro-AI explain how the resulting chart was obtained, and the explanation is shown as output in the Jupyter Notebook, along with the chart which is displayed by the show()
command.
The Insights text returned by Vizro-AI explains how to manipulate the traffic data. The Code section describes the steps the code snippet follows to generate the line graph requested.
The chart returned looks as follows:
Build More Charts
I created some additional charts to further illustrate the traffic to our documentation, as follows:
# Total views of the top performing stable pages
top_performing_pages_fig = vizro_ai.plot(df, "Collate rows of data for Path where Version==stable. Create a horizontal bar chart describing the total Views for the top 5 pages. Add the numbers to each bar. Decrease font size of marks", explain=True)
top_performing_pages_fig.show()
# Top 5 performing pages on stable by date
top_pages_by_date_fig = vizro_ai.plot(df, "Collate rows of data for Path where Version==stable. Create a line graph for the total Views per Date for the top 5 Paths", explain=True)
top_pages_by_date_fig.show()
“Collate rows of data for Path where Version==stable. Create a horizontal bar chart describing the total Views for the top 5 pages. Add the numbers to each bar and title ‘Total views for top 5 stable pages’. Decrease font size of marks” and “Collate rows of data for Path where Version==stable. Create a line graph for the total Views per Date for the top 5 Paths”
Vizro-AI has done the heavy lifting for me by generating the code to manipulate the data and generate a set of charts, which are useful in themselves. More useful still would be to group them together in combination to make a complete dashboard.
Create a Vizro Dashboard
You can use Vizro in the same Jupyter Notebook as the Vizro-AI code above. Make sure to pip install vizro
as the Vizro documentation describes. Here is some code for the skeleton of a simple dashboard without the chart generation:
from vizro import Vizro
import vizro.models as vm
import vizro.plotly.express as px
first_page = vm.Page(
title="Documentation traffic dashboard",
layout=vm.Layout(
grid=[
[0, 2],
[1, 2],
],
),
components=[
# TO DO
],
)
...
The # TO DO
section is where we add each of the charts.
There are two options at this point:
- Use Vizro-AI to generate the charts each time the dashboard is generated
- Use the Python code that Vizro-AI returned to call directly to Plotly.
The first option requires less code but will be slower to return and more expensive because it uses Vizro-AI, which calls OpenAI. The second option is faster but requires more code manipulation.
Here's a cell containing the dashboard code that demonstrates the first option with functions that call through to Vizro-AI (If you plan to run this for yourself, make sure you're using the Notebook in my repo, have loaded the data and stepped through the cells that set up the calls to Vizro-AI):
# Dashboard using Vizro-AI calls only
from vizro import Vizro
import vizro.models as vm
import vizro.plotly.express as px
first_page = vm.Page(
title="Documentation traffic dashboard",
layout=vm.Layout(
grid=[
[0, 2],
[1, 2],
],
),
components=[
# Latest and stable by date
vm.Graph(figure=compare_versions_fig),
# Top performing stable pages
vm.Graph(figure=top_performing_pages_fig),
# Top 5 stable pages by date
vm.Graph(figure=top_pages_by_date_fig),
],
)
dashboard = vm.Dashboard(pages=[first_page])
Vizro().build(dashboard).run(port=8006)
Here's a slightly different version, which uses the second option to generate one of the charts. I've taken the opportunity to tweak the Python code slightly to change the colors of the lines, which is about my limit for Plotly manipulation! (Again, if you plan to run this for yourself, make sure you're using the Notebook in my repo, have loaded the data, and stepped through the cells that set up the chart creation functions).
# Dashboard from Vizro-AI calls and using Vizro-AI generated chart code
from vizro import Vizro
import vizro.models as vm
import vizro.plotly.express as px
from vizro.models.types import capture
import plotly.graph_objects as go
import pandas as pd
@capture('graph')
def compare_versions_custom_chart(data_frame=None):
if data_frame is None:
data_frame = pd.DataFrame()
data_frame['Date'] = pd.to_datetime(data_frame['Date'])
# Group by Date and Version and sum the Views
aggregated_df = data_frame.groupby(['Date', 'Version'])['Views'].sum().reset_index()
# Pivot the dataframe to have Versions as columns
pivot_df = aggregated_df.pivot(index='Date', columns='Version', values='Views')
# Fill NaN values with 0
pivot_df.fillna(0, inplace=True)
data_frame = pivot_df.reset_index()
# Create a line trace for each version
trace1 = go.Scatter(x=data_frame['Date'], y=data_frame['latest'], mode='lines', name='latest', line=dict(color='#689F38'))
trace2 = go.Scatter(x=data_frame['Date'], y=data_frame['stable'], mode='lines', name='stable', line=dict(color='#FDC935'))
# Define the layout
layout = go.Layout(title='Views per Date for latest and stable Version', xaxis=dict(title='Date'), yaxis=dict(title='Views'))
# Create a Figure and add the traces
fig = go.Figure(data=[trace1, trace2], layout=layout)
# Return the figure
return fig
compare_versions_custom_fig = compare_versions_custom_chart(data_frame=df)
first_page = vm.Page(
title="Documentation traffic dashboard",
layout=vm.Layout(
grid=[
[0, 2],
[1, 2],
],
),
components=[
# Latest and stable by date
vm.Graph(figure=compare_versions_custom_fig),
# Top performing stable pages
vm.Graph(figure=top_performing_pages_fig),
# Top 5 stable pages by date
vm.Graph(figure=top_pages_by_date_fig),
],
)
dashboard = vm.Dashboard(pages=[first_page])
Vizro().build(dashboard).run(jupyter_mode="external")
You can download the Jupyter Notebook to try out the dashboard with your own Read the Docs data. It looks as follows with the fake data I supplied.
One of my colleagues (thanks, Nadija!) gave me a tip that you can run the dashboard in the Notebook and then view it in a separate browser window by viewing the port you choose as follows:
Vizro().build(dashboard).run(port=8006) # localhost8006 in the browser
Alternatively (thanks, Antony!), as I’ve shown in the second dashboard example above, you can generate a clickable link to view the dashboard as follows:
Vizro().build(dashboard).run(jupyter_mode="external")
Wrapping Up
In this example, I showed how to use Vizro-AI to generate Plotly charts to visualize documentation traffic, and then built those charts into a Vizro dashboard.
If you have data science and Python skills and a talent for design, you may want the challenge of building a dashboard with Plotly and Dash. But, to someone like me without those skills, it’s a game changer to be able to use OpenAI and achieve the output above. I now have a useful visualization for Read the Docs traffic data in about 50 lines of code. It looks professional and is easily extensible and relatively easy to share. With more effort, I could improve it further by adding customizations such as filters, parameters, or separate navigable pages.
What’s more, I can collaborate on the dashboard code with my colleagues to adapt it for other Read the Docs projects. I’ve used a Jupyter Notebook to make it easy to demonstrate the project, but this approach works equally well in a Python script, making it easily sharable and maintainable in version control. I can also deploy the dashboard so my colleagues can access it directly without running the code.
Our team now has a useful and usable dashboard for tracking documentation impact, put together by a technical writer in an afternoon. Who can ask for more?
I’d like to thank my colleagues, particularly Nadija, Anna, and Joe, for several rounds of review feedback as I was putting this post together.
Published at DZone with permission of Jo Stichbury, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments