I am trying to collect some analytics data on my streamlit app that’s hosted on streamlit cloud. I tried adding the tracking code for Microsoft Clarity to the head file. I see some tracking metrics pop up but the numbers looks quite off.
As part of the instructions, I had to add the script tag in the file.
If applicable, please provide the steps we should take to reproduce the error or specified behavior.
Expected behavior:
I am expecting more actual metrics popping up. Example, I know users from other countries used to login to the app, but it doesn’t show up here. Also the heatmaps tab doesn’t capture properly the user journey in the website.
I’ve inserted the Clarity script into our Streamlit app but the Clarity recordings do not show any screens or even clicks. All it shows is a gray line.
In order to include the Clarity script in the head tag, I inserted a javascript function to find the head tag and append a script element containing the Clarity snippet.
document.addEventListener("DOMContentLoaded", function (event) {
let headElements = document.getElementsByTagName("head");
let headElement = headElements[0]
let textNode = document.createTextNode("inserting clarity here")
let clarityScript = document.createElement("script");
clarityScript.type = "text/javascript"
let code = `(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "abc123456789");`
clarityScript.appendChild(document.createTextNode(code));
headElement.appendChild(textNode);
headElement.appendChild(clarityScript);
});
I used streamlit_javascript to run this javascript at the start of our app:
import streamlit_javascript
...
with open('static_resources/append_clarity.js') as f:
st_javascript(f"{f.read()}")
Although I used this script to find the first head tag, the rendered page has a head tag above it.
Here’s an abbreviated outline of the html document…
<iframe>
<html>
<head> <---- this is first head tag (but not found by my script)
<body>
<div>
...
<div>
<html>
<head> <--- this is the head element where my script inserts clarity
@agni
How did you add it to the head file? I have added in the main.py file with st.markdown and the clarity script tag code. It is not working at all
How can I make it working? Please help me with this as soon as possible.
I have manage to find a solution to add the clarity script to the head of each page of streamlit app. So my solution was to create a add_track.py script with the following information:
from bs4 import BeautifulSoup
import pathlib
import shutil
import streamlit as st
CLARITY_ID = "clarity_analytics"
CLARITY_SCRIPT = """
<script type="text/javascript">
{your clarity script}
</script>
"""
def inject_ga():
index_path = pathlib.Path(st.__file__).parent / "static" / "index.html"
soup = BeautifulSoup(index_path.read_text(), features="html.parser")
if not soup.find(id=CLARITY_ID):
bck_index = index_path.with_suffix('.bck')
if bck_index.exists():
shutil.copy(bck_index, index_path)
else:
shutil.copy(index_path, bck_index)
html = str(soup)
new_html = html.replace('<head>', '<head>\n' + CLARITY_SCRIPT)
index_path.write_text(new_html)
inject_ga()
Then when I run the app in my docker file I need to run this code and the one that runs the streamlit, something like this:
poetry run python app/add_track.py && poetry run streamlit run app/streamlit_app.py
I am using poetry btw
Now, I am facing another issue when I am using streamlit platform to deploy the app I am unable to run the command line above. I can only run it when deploying with docker using a service like heroku
Kudos to franciscodelca for the trick to insert the Clarity script in the head of each Streamlit page.
It wasn’t immediately obvious what it was doing. His script finds the index.html in the Streamlit virtual environment files.
For example:
your_home_path/.venv/lib/python3.10/site-packages/streamlit/static/index.html
And then it checks if there’s a script tag with an id=“clarity_analytics”.
If not, it adds your clarity script to the html file and saves it.
This works because this index.html file is the parent file used by Streamlit for the entire Streamlit page.
Brilliant approach!
Now the trick is how to run it for your deployed app?
In our case, we’re deploying the app on Azure using an Azure DevOps pipeline.
To get this to work, I added a script step to our pipeline yaml config file which:
– activates the virtual environment
– runs the Python script to inject the Clarity script tag (config_clarity.py)
– displays the modified index.html file (for confirmation)
Here’s the script I’m using for Azure DevOps…
- script: |
source antenv/bin/activate
python config_clarity.py
echo cd antenv/lib/python3.10/site-packages/streamlit/static
cd antenv/lib/python3.10/site-packages/streamlit/static
echo ls -la
ls -la
echo cat index.html
cat index.html
Clarity is now working for our Streamlit app. The only issue so far: a custom component doesn’t appear…strange.
I modified the ‘add_track.py’ code and ran ‘add_track.py’ before executing ‘stramlit run app.py’.
After the program started, I found the injected clarity script in the source code of localhost:8051.
But in the browser’s debug page, there is no clarity report request in the Network Tab. Only GET ‘https://www.clarity.ms/tag/olm4y3l6w3’ is ‘200 OK’, and GET ‘https://www.clarity.ms/s/0.7.49/clarity.js’ is ‘429 Too Many Requests’.
And no report information can be found in clarity.microsoft.com.
What may be the reason?
from bs4 import BeautifulSoup
import pathlib
import shutil
import streamlit as st
CLARITY_SCRIPT = """
<script type="text/javascript">
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "<--my-clarity-tag-->");
</script>
"""
INJECTION_COMMENT = "<!-- Clarity script injected -->"
def inject_ga():
index_path = pathlib.Path(st.__file__).parent.joinpath('static', 'index.html')
soup = BeautifulSoup(index_path.read_text(), features="html.parser")
if INJECTION_COMMENT not in str(soup):
bck_index = index_path.with_suffix('.bck')
if bck_index.exists():
shutil.copy(bck_index, index_path)
else:
shutil.copy(index_path, bck_index)
html = str(soup)
new_html = html.replace('<head>', '<head>\n' + CLARITY_SCRIPT + INJECTION_COMMENT)
index_path.write_text(new_html)
print('Clarity inject Done\n')
else:
print('Clarity injected. Skipping.')
if __name__ == '__main__':
inject_ga()
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.