How to add Google Analytics or JS code in a Streamlit app?

@suryatejreddy do you know if changing the static index page works when deployed with a cloud platform like Heroku?

@dimalvovs @Quoc_Tran @suryatejreddy

I am having trouble implementing google analytics. I was successful at adding it to local deployment by changing the static index.html file. My problem is my app is hosted on Heroku and that solution doesn’t work for that host.

Do you mind telling me how you host your app? I tried a virtual server on AWS but there were all sorts of issues with the default port and getting the app to run after closing the terminal window.

Any assistance would be highly appreciated!


With streamlit 0.75+, you can add google analytics directly in the script file using components iframe. You can check my example here: COVID-19/ at master · QuocTran/COVID-19 · GitHub No need to change static file index.html .



Hi Quoc,

Thank you for all the helpful information you have provided so far - I really appreciate it!

I have successfully configured Nginx reverse proxy using the script you provided. I am in the final stretch and have one last question for you.

I noticed in your Covid you have Iframes for Google Analytics, Disqus comments, and Facebook comments. They all are HTML pages on your domain.

How do you configure Nginx to create and serve those pages? I have spent many hours researching unsuccessfully. I think it has to do with adding them to the var/www/html directory. Do you also have a Nginx configuration script like location{… to serve the pages? Is there also any specific configuration for SSL certificate?

The very last question is, does your Google Analytics report clicks on widgets or just page views? I used the same GA global tag you used with my account information, but was unsure if it reports all activity because of the Iframe and Nginx reverse proxy configurations?

I have spent many hours on this and would be willing to pay you for all the support you have offered.

Thank you in advance for any additional info you can offer.

Hi QT,

Trying to get this working, but no users are showing up on Real-Time tracking. In your example, why is st.components.v1.iframe(‘Google Analytics’, height=1, scrolling=False) commented out and what is the purpose of the URL address in the iframe?

Also, any updates on a more general solution to this problem? A plugin or option would be helpful.

Does this still work? I tried to add a function in the index.html and run it (from example when clicking a button) but it doesn’t execute it

1 Like

I’m stuck on this seemingly simple task, too. QT’s approach doesn’t seem to work for me currently.

Obviously, basic analytics, including standard javascript-based tools, are pretty vital for the ecosystem for anyone who wants to measure impact or user behavior, which is most of us. If someone from the Streamlit product team wants to sketch out how this should be accomplished, I am sure that some of us organisms in the ecosystem would be interested in creating some options.

I tested and it is possible to add Google Analytics (or any custom HTML) to a streamlit app using Github Pages as static web server. I wrote a step by step tutorial on my blog

Hi guys!

My app runs inside a docker container and I tried the following without success:

        <!-- Global site tag (gtag.js) - Google Analytics -->
        <script async src=""></script>
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());

            gtag('config', 'G-2QP9LNWWSV');
    width=0, height=0

I think the issue is that the components element adds an extra <head></head> tag to the website (I checked this with Chrome Dev Tools), whereas the google analytics tab should go right after the first <head> tag of the app. Basically the component just adds a webpage within the webpage (I think) :confused:

Hi all:

This (I run into it on GitHub) ended up working for me:

def inject_ga():
    GA_ID = "google_analytics"

    # Note: Please replace the id from G-XXXXXXXXXX to whatever your
    # web application's id is. You will find this in your Google Analytics account
    GA_JS = """
    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src=""></script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'G-XXXXXXXXXX');

    # Insert the script in the head tag of the static template inside your virtual
    index_path = pathlib.Path(st.__file__).parent / "static" / "index.html"'editing {index_path}')
    soup = BeautifulSoup(index_path.read_text(), features="html.parser")
    if not soup.find(id=GA_ID):  # if cannot find tag
        bck_index = index_path.with_suffix('.bck')
        if bck_index.exists():
            shutil.copy(bck_index, index_path)  # recover from backup
            shutil.copy(index_path, bck_index)  # keep a backup
        html = str(soup)
        new_html = html.replace('<head>', '<head>\n' + GA_JS)


You also need to import the following libraries into your file (or whatever your app file is):

import pathlib
from bs4 import BeautifulSoup
import logging
import shutil

I’ve gotten Google Analytics to function properly by adding the GA global site tag JS code above to the default /site-packages/streamlit/static/index.html file, which is deployed in my Docker container. See this thread for details. Adding a Meta description to your streamlit app - #7 by Greg

1 Like

awesome!!. I hope to deplay my web app soon!!

Yes, it’s a head inside an iframe, hence I think something like this will make it work:

<script crossorigin='anonymous'>
add script

In addition to that, whenever the script accesses window or document, you should use parent.window and parent.document.

Hi @ozgurdugmeci

I am trying to implement the statcounter code. Does it look something like this?

        <!-- Default Statcounter code for product-tour-with-analytics -->
        <script type="text/javascript">
        var sc_project=AAAAAAA; 
        var sc_invisible=0; 
        var sc_security="BBBBB"; 
        var scJsHost = "https://";
        document.write("<sc"+"ript type='text/javascript' src='" + scJsHost+
        <noscript><div class="statcounter"><a title="Web Analytics Made Easy -
        Statcounter" href="" target="_blank"><img
        class="statcounter" src=""
        alt="Web Analytics Made Easy - Statcounter"
        <!-- End of Statcounter Code -->
""", unsafe_allow_html=True

I insert the above code before I render any widgets (buttons, forms, expanders etc.)

Is that correct?

Hi @C_Quang ,
This is how handle the statcounter code:

import streamlit.components.v1 as components

#this code below is the statcounter tracking code
takip= """
<!-- Default Statcounter code for euro_stats -->
<script type="text/javascript">
var sc_project='somenumber'; 
var sc_invisible=1; 
var sc_security="sometext"; 
<script type="text/javascript"
<noscript><div class="statcounter"><a title="web counter"
href="" target="_blank"><img
alt="web counter"
<!-- End of Statcounter Code -->
components.html(takip,width=200, height=200)   

Thanks @ozgurdugmeci I’ll be keen to give that a go. I’ll let you know if it works for me

One more thing,
import streamlit.components.v1 as components on the top
and add the rest of the lines at the very end of your script

Do we need to add the component to all the pages or will it be sufficient to add it to the homepage ?

Any updates on this? I haven’t been able to integrate Google Analytics with my application using the suggested implementations that have been posted the last couple of years

I’ve tried that, it didn’t work for me. My app is hosted in Streamlit community cloud.