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

This wrecked my server… Cannot go back the tags are permanently in the static files now, how do we reset them ? Thanks

Edit : For those looking for a way, I resolved it by recreating the conda environment I used for the script. Apparently the static files are stored in it. If it’s the base env, you’ll need to create a new one.
The right way would be to fix the static index.html but I messed it and got a blank file ^^

Has anyone tried to iframe their app to a standalone html page?
You could then add google analytics to the html page containing the iframe.
Just an idea that could work. I myself have not tried it.

I’m really struggling with this, and have seen many different implementations of the Google Analytics code. It seems straightforward until I actually try it.

I’m currently trying this at the end of my .py file:

components.html(
    """
    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
    
      gtag('config', 'G-XXXXXXXXXX');
    </script>
    """
)

I’ve seen an example that has:

components.html(
        f"""

…in the HTML method explanation halfway down the official announcement of Streamlit components page. I don’t know what that extra 'f" is for, but I tried to add it and didn’t fix anything.

I tried three single quotes ''' vs. three double quotes """ to set off the code block. No change.
I tried indenting the code inside the components.html command. No change.
I visit my Google Analytics site and get nothing in the Realtime report.

Not sure if it’s related to the “new” Google Analytics G- code vs. the older UA- code.

1 Like

The f in front of the the string means it’s an f-string which “provide a way to embed expressions inside string literals”. Not required in your case. I think that using an f-string would actually thow an exception.

The components.html run the code inside a iframe (see docs). I think the iframes inside Streamlit are sandboxed, which would explain why you don’t get any metrics back. Have you tried putting it in a markdown component?

st.markdown(
    """
    <script>Your JS code</script>
    """,
    allow_unsafe_html=True
)

Thanks. I tried using components and markdown, both separately and together on your suggestion but still nothing works. I tried to put in a <head> tag, I moved the code block to the top of the file, I used just the UA- tag, then just the G- tag, then both together. I tried to focus not on my work-hosted website but just on the share.streamlit.io site to simplify.

I’ve looked through Google Analytics 15 different times and it has the correct URL. I’ve tried to visit in my browser, on my phone, and using the Send Test Traffic button in Google Analytics but still no users show up in the Realtime report. I don’t understand what’s wrong.

Never did get this to work. Also tried Plausible analytics which also uses JS, and that didn’t work either. I did get Clicky and Statcounter to work, neither of which use JS.

2 Likes

is it gonna be like below?
st.markdown(tracking code, unsafe_allow_html=True)

I used statcounter.
components.html(tracking code, width=200, height=200) worked for me.

1 Like

Yeah, statcounter worked for me too. Will also try out this and review

1 Like

@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!

Thanks

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/app.py at master · QuocTran/COVID-19 · GitHub No need to change static file index.html .

4 Likes

@Quoc_Tran

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 app.py 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:

components.html(
    """
        <!-- Global site tag (gtag.js) - Google Analytics -->
        <script async src="https://www.googletagmanager.com/gtag/js?id=G-2QP9LNWWSV"></script>
        <script>
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());

            gtag('config', 'G-2QP9LNWWSV');
        </script>
    """,
    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="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
    <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'G-XXXXXXXXXX');
    </script>
    """

    # Insert the script in the head tag of the static template inside your virtual
    index_path = pathlib.Path(st.__file__).parent / "static" / "index.html"
    logging.info(f'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
        else:
            shutil.copy(index_path, bck_index)  # keep a backup
        html = str(soup)
        new_html = html.replace('<head>', '<head>\n' + GA_JS)
        index_path.write_text(new_html)


inject_ga()

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

import pathlib
from bs4 import BeautifulSoup
import logging
import shutil
1 Like

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