To add live chat to Flask you need a Jinja base template, one include and a setting that says whether the widget is on. Flask has no built-in notion of a global page footer, so the habit that works is the plain one: every public template extends a base file, the base file includes the Talkmio snippet just before the closing body tag and a configuration value decides whether it renders. This guide shows that setup step by step, adds a context processor that keeps templates tidy, and covers blueprints, content security policy and the checks to run before you announce the chat.
Talkmio is an AI live chat for websites. Its assistant, Mio, answers visitors in their own language from your website, FAQ and uploaded documents, and hands the conversation to your team when it cannot answer. Nothing in Flask needs to change for that: the snippet is a single script tag, and no Python package is involved.
Before You Add Live Chat to Flask
Create a free account at app.talkmio.com, confirm your e-mail and add your website under Websites. You receive a site key and an install snippet. In the examples, SCRIPT_ADDRESS_FROM_YOUR_SNIPPET stands for the script address. Use the real value from your own snippet, unchanged.
Next, find the file that all your public pages extend. In most Flask projects it is templates/base.html. Flask renders templates with Jinja, and the Flask templating guide explains inheritance, includes and autoescaping. If you use blueprints for an admin area, note which templates belong to the public site, because the chat should appear only there.
The Quick Version
For a small site, paste the snippet into the base template and stop. It works, and you can improve it later.
<!-- templates/base.html -->
{% block content %}{% endblock %}
<script async src="SCRIPT_ADDRESS_FROM_YOUR_SNIPPET"></script>
</body>
</html>
The weakness of this version is that the widget loads everywhere, including your development server and your admin pages, and the address is buried in a template. The next sections fix both problems.
Add Live Chat to Flask With a Config Flag
Flask keeps settings in app.config, and the configuration handling documentation describes several ways to fill it. Read the script address from an environment variable, so that each environment can have its own value, or none.
# config.py
import os
class Config:
TALKMIO_SCRIPT_SRC = os.environ.get("TALKMIO_SCRIPT_SRC", "")
# app.py
from flask import Flask
from config import Config
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
return app
On your production server, set TALKMIO_SCRIPT_SRC to the address from your snippet. On your laptop, leave it empty. Now the widget exists only where you ask for it, and there is no need to compare environment names in the template.
Use a Partial and a Context Processor
You can read config directly in a Jinja template, because Flask makes it available there. That works, but a context processor gives templates a clear, named variable and keeps configuration out of the markup.
# app.py (inside create_app)
@app.context_processor
def inject_talkmio():
return {"talkmio_src": app.config.get("TALKMIO_SCRIPT_SRC", "")}
<!-- templates/_talkmio.html -->
{% if talkmio_src %}
<script async src="{{ talkmio_src }}"></script>
{% endif %}
<!-- templates/base.html -->
{% block talkmio %}{% include "_talkmio.html" %}{% endblock %}
</body>
</html>
Jinja escapes the value because autoescaping is on for HTML templates in Flask, so an unexpected character in the variable cannot break the page. That is a good reason to keep the address in a variable rather than concatenating strings in Python.
| Approach | Effort | Per-environment control | Best for |
|---|---|---|---|
| Snippet pasted into base.html | Lowest | No | Prototypes and single-server sites |
| Include with a config check | Low | Yes | Most Flask apps |
| Context processor and partial | Medium | Yes | Apps with several templates and blueprints |
| Google Tag Manager container | Medium | Yes | Teams that already manage scripts there |
Blueprints, Admin Areas and Per-Page Opt-Out
Large Flask apps split code into blueprints. The public blueprint renders templates that extend base.html, and the admin blueprint usually has its own base. If admin pages extend the same file, empty the block in the admin base template.
<!-- templates/admin/base.html -->
{% extends "base.html" %}
{% block talkmio %}{% endblock %}
The same trick works for a single page, such as a print view or a checkout step you want to keep clean. Keep the list of exceptions short. Visitors expect help on pricing and checkout pages, where they hesitate most. If you prefer to manage the script outside your templates, our guide to live chat and Google Tag Manager describes that route.
Content Security Policy, Caching and Speed
If your app sends a content security policy, for example through the Flask-Talisman extension or from your reverse proxy, the policy must allow the script and the connections the widget makes. Copy the addresses from your snippet into the matching directives and then check the browser console on a production page for blocked requests. If you use a nonce for inline scripts, remember that the Talkmio snippet is an external script tag, so it needs an allowed source, not a nonce.
Caching is straightforward. Every visitor gets the same markup, so a reverse proxy, a CDN or a page cache can serve it. Widget colours, position, texts and business hours are set in Talkmio under Websites and apply within five minutes, without a deployment. For performance, the async attribute keeps the script from blocking the first paint. Our guide on live chat widget page speed explains how to measure the effect.
Deployment: Gunicorn, Docker and Reverse Proxies
The environment variable approach fits modern deployment well, because most platforms already pass configuration that way. In a container, add TALKMIO_SCRIPT_SRC to the service definition or the secrets file for production, and leave it out of the development compose file. Under a process manager, make sure the variable is part of the service environment, because a variable exported in an interactive shell is not seen by a worker that was started earlier.
The Flask deployment guide describes the usual production stack: an application server behind a reverse proxy. The widget needs nothing special from the proxy, because it is a static script reference in the HTML. Two details are worth checking. First, if your proxy compresses or rewrites HTML, make sure it does not strip the script line. Second, if you serve the site over HTTPS only, which you should, check that no part of your page references the script with an insecure address. A mixed-content warning in the console is a sign that something in the template builds the address by hand.
Multilingual Flask Sites
Many Flask projects serve several languages, often with an extension such as Flask-Babel or with separate templates per language. The snippet does not change per language. Mio replies in the language the visitor writes in, including Lithuanian, English, German, Polish, Russian, Spanish and French and more than thirty others, and the widget is translated as well. A question in one language can be answered from pages written in another, so you do not need to translate every page before launch. In the widget settings you can leave the language on auto-detect or fix it. Auto-detect is the better default for a site where visitors choose their own language, and you can test both settings on a staging page before you decide. Changes to widget settings apply within five minutes.
Review a few answers in each major language with a native speaker, and add question and answer pairs where the wording of your product differs from what people say. Our guide on multilingual live chat describes the review routine.
Teach Mio From Your Flask Site
With the snippet in place, open Mio AI, then Knowledge base, in Talkmio and add your deployed site. Mio reads every public page on the same domain and respects robots.txt. Routes behind a login are not public, so Mio will not see them. If your documentation, price list or policies live elsewhere, upload them as files: PDF, DOCX, TXT, MD, CSV and HTML are supported, up to 15 MB each.
Write business instructions that say what you sell, the tone to use and what Mio must never promise. Use Try Mio to test questions and see which pieces of content each answer used. After a release that changes prices or policies, use the re-read option. Mio answers only from your content and never invents prices or policies. If your project uses another framework as well, the guides to adding live chat to Laravel and to adding live chat to any website use the same ideas.
Common Problems
- The bubble does not appear. Check that the environment variable is set in the process that runs the app, not only in your shell. Application servers and process managers often start with a clean environment.
- It appears in development. The variable is set locally. Unset it or use a separate configuration class.
- It appears twice. The partial is included in both a parent and a child template, or a tag manager loads it as well. View the page source and count the script tags.
- It shows in the admin area. The admin base extends the public base. Empty the block there.
- Blocked by the browser. A content security policy or an extension blocks it. Read the console.
- An old template is served. If you run with template caching in production, restart the workers after you change a template.
When a problem is hard to reproduce, compare the rendered HTML from production with a local render of the same route. The difference is almost always an environment variable, a cache or a proxy rule, not the snippet itself.
For consent banners, read our note on cookies and consent for chat widgets to decide when the widget should load.
Test Before You Announce It
- Set the variable on production, restart the app and open a page in a private window. The bubble appears.
- View the source and confirm one script tag, near the end of the body.
- Run the app locally without the variable. The widget is absent.
- Ask Mio three questions that customers often ask. Each answer should come from your pages.
- Ask for a person. The conversation should reach the Inbox with a needs-human badge, and your browser should notify you.
- Open a page with the block emptied and confirm the bubble is gone.
- Test on a phone, because the bubble must not cover important buttons.
Frequently Asked Questions
Is there a Flask extension for Talkmio?
No extension is needed. The Talkmio snippet is a plain script tag, so you add it to a Jinja template. There is no Python package to install and no server-side code to write. The WordPress plugin is only for WordPress. Any Flask app that renders HTML can use the snippet in its base template.
Where should I put the snippet in a Flask app?
Put it in a partial such as templates/_talkmio.html and include it from base.html just before the closing body tag, inside its own block. A block lets child templates, such as admin pages, empty it. Use the public layout only, so your back office stays free of the widget.
How do I keep the widget out of development?
Read the script address from an environment variable into app.config, expose it with a context processor and render the script only when the value is not empty. Set the variable on production only. This avoids comparing environment names in templates and keeps test chats out of your Inbox.
Will it work with Flask blueprints?
Yes. The widget lives in the template layout, not in a blueprint. If the public and admin blueprints share a base template, empty the block in the admin base. Keep exceptions few, because visitors expect help on pricing and checkout pages as well.
Does Mio know about my Flask content automatically?
After you add your deployed site to the knowledge base, Mio reads every public page on the same domain and respects robots.txt. Pages behind a login are not read. After releases that change content, use the re-read option, and upload private documents as files.
Can I try it before paying?
Yes. The Free plan includes one operator, one website, 50 AI answers a month, 50 tickets a month and 20 knowledge base pages, with no card needed. Paid plans add operators, websites, AI answers and the e-mail channel. Check the pricing page for current figures.
The Bottom Line
To add live chat to Flask, put the snippet in a partial, include it from the base template inside a block, and let a config value read from the environment decide whether it renders. Empty the block on admin and special pages, allow the script in your content security policy and test on a phone. Then teach Mio from your public pages. Start free with Talkmio, add your site and see how many of your visitors’ questions Mio can answer on its own.
