Injecting HTML/GTM/Analytics into Dockerized Streamlit Apps

Hey Streamlit community! :waving_hand:

I’ve seen many people struggling with adding Google Tag Manager, analytics, or custom HTML to their Streamlit apps, especially when running in Docker. After trying multiple approaches (monkey patching, runtime injection, etc.), I finally found a reliable solution that I want to share.

The Problem

Streamlit doesn’t provide a native way to modify the HTML <head> or <body> sections. This makes it challenging to add:

  • Google Tag Manager
  • Analytics tracking (GA4, Facebook Pixel, etc.)
  • SEO meta tags
  • Custom scripts

The challenge is even bigger with Docker due to read-only filesystems and container isolation.

The Solution

Thanks to @snehankekre’s suggestion in this thread about using SED to modify index.html, I expanded on this approach to create a comprehensive, production-ready solution for Docker environments.

The build-time injection approach using SED modifies Streamlit’s static HTML during Docker image build. This means:

  • :white_check_mark: No runtime overhead
  • :white_check_mark: Works with read-only containers
  • :white_check_mark: 100% reliable
  • :white_check_mark: Production-ready

How It Works

Simply add this to your Dockerfile:

# Inject GTM using sed
ARG GTM_ID
RUN sed -i "/<\/head>/i\
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':\
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],\
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=\
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\
})(window,document,'script','dataLayer','${GTM_ID}');</script>" \
$(python -c "import streamlit, os; print(os.path.join(os.path.dirname(streamlit.__file__), 'static', 'index.html'))")

Then build with:

docker build --build-arg GTM_ID=GTM-YOURCODE -t your-app .

Complete Solution

Building on @snehankekre’s SED approach, I’ve created a comprehensive repository with:

  • :file_folder: Modular injection scripts (GTM, Analytics, SEO, custom HTML)
  • :clipboard: Ready-to-use Dockerfiles
  • :rocket: Examples and documentation
  • :hammer_and_wrench: Makefile for easy operations

GitHub Repository: streamlit-html-injection-docker

The repo includes scripts for:

  • Google Tag Manager
  • Google Analytics 4
  • Facebook Pixel
  • Microsoft Clarity
  • SEO meta tags (Open Graph, Twitter Cards)
  • Custom HTML injection from files

Example Use Cases

  1. Adding GTM to your app:

    docker build --build-arg GTM_ID=GTM-ABC123 -t my-app .
    
  2. Full SEO + Analytics:

    docker build \
      --build-arg GTM_ID=GTM-ABC123 \
      --build-arg SEO_TITLE="My Dashboard" \
      --build-arg SEO_DESCRIPTION="Analytics dashboard" \
      -t my-app .
    

Why This Approach?

After testing runtime patching, monkey patching, and various other methods suggested in different threads, the build-time SED injection (as suggested by @snehankekre) proved to be the most reliable. It works every time, has zero runtime overhead, and is compatible with any Docker deployment.

Credits

Special thanks to @snehankekre for the original SED suggestion that inspired this complete solution!

Hope this helps others facing the same challenge! Feel free to contribute or suggest improvements on GitHub. :folded_hands: