Python Flask Online Visitor Tracking System

Introduction

We will discuss here how to build a simple online visitor tracking system using Python Flask. Every website owner would like to know the progress to the count of the online visitors because it gives them overall idea on the website’s analytical measurements. It will also give them how to make improvements on the websites.

We will use here @app.before_request decorator which Flask API provides to track your visitor when a visitor lands on your website.

This example will give you an idea how to implement such system to track visitors who visit your website on daily basis.

Prerequisites

Python 3.8.0, Flask 1.1.1, MySQL 8.0.17, PyMySQL 0.9.3

Related Posts:

Creating MySQL Table

We need to create MySQL table to store visitor information.

In the following table we store how many times a visitor has visited application or website. We store visitor’s IP address, which URLs visitor visits, from which page or URL visitor navigates, if there is any query parameters in the URL, on which browser visitor opens the website.

We have also another flag whether the visitor is unique or not. So it depends on how you are going to implement the functionality. In this basic example I have not worked on this flag.

CREATE TABLE `visits_log` (
  `log_id` int unsigned NOT NULL AUTO_INCREMENT,
  `no_of_visits` int unsigned NULL,
  `ip_address` varchar(20) NULL,
  `requested_url` tinytext NULL,
  `referer_page` tinytext NULL,
  `page_name` tinytext NULL,
  `query_string` tinytext NULL,
  `user_agent` tinytext NULL,
  `is_unique` tinyint NOT NULL DEFAULT '0',
  `access_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`log_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Creating Project Directory

Create a project root directory called python-flask-mysql-online-visitor-tracker as per your chosen location.

We may not mention the project’s root directory name in the subsequent sections but we will assume that we are creating files with respect to the project’s root directory.

Configure Flask

We here configure application through flask framework. Create a file called app.py with the below code.

Here we need to assign secret key otherwise session will not work in Python. The secret key, ideally, should be in encrypted format.

We have also configured the session timeout – 30 minutes because flask expires session once you close the browser unless you have a permanent session.

Basically a session will exist for 30 minutes and in this 30 minutes a user’s visits will be unique for a particular URL. So to set the flag is_unique in table vistis_log you need to work on this.

from flask import Flask
from datetime import timedelta
	
app = Flask(__name__)
app.secret_key = "secret key"
app.config['PERMANENT_SESSION_LIFETIME'] =  timedelta(minutes=30)

Database Configuration

We create the below db.py Python script to setup the MySQL database configurations for connecting to database and storing visitor information into visits_log table.

We need to configure database connection with flask module and that’s why we have imported app module and setup the MySQL configuration with flask module.

Make sure to change the database configuration values according to your database setup.

from app import app
from flaskext.mysql import MySQL

mysql = MySQL()
 
# MySQL configurations
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = 'root'
app.config['MYSQL_DATABASE_DB'] = 'roytuts'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)

Configure Utility

I will create one general purpose utility Python script that will provide some utility functions to be used throughout the whole application wherever required.

We create a file called config.php with the following source code.

We check the key DNT in the requested http header and if its value is 1 then we don’t track visitors otherwise we will track the visitors if other conditions also meet.

We ignore IPs, for example, localhost, 127.0.0.1 etc because from localhost you won’t get real visitors.

I have created another function that will help us whether we want to consider a user is unique for a particular time period. For example, as I had said earlier that we want to consider a visitor unique if he/she is active for 30 minutes on the same browser.

from flask import request, session

DNT_TRACK = True #False
IGNORE_IPS = set(['127.0.0.1'])

def is_tracking_allowed():
	#print(request.headers)
	if 'DNT' in request.headers and request.headers['DNT'] == 1:
		return False
	if request.remote_addr in IGNORE_IPS:
		return False
	return True

def track_session():
	if 'track_session' in session and session['track_session'] == True:
		return True
	else:
		return False

Log Visitors

Now we will log visitors into MySQL database table. We create a file called visitor.py.

We first check whether session tracking is allowed, i.e., if you are going to consider a visitor unique for a time period.

If session tracking is allowed then we check if the visitor is visiting the same page within 30 minutes. If visitor visits the same page then we don’t store the same information into database otherwise we store the details into database.

We have used session.modified = True otherwise you won’t be able to update the session key’s value.

If session tracking is not allowed then every time a visitor visits a page we store details into MySQL table. In this case your database table will grow unnecessarily.

import config
import pymysql
from db import mysql
from flask import request, session

def track_visitor():
	if not config.is_tracking_allowed():
		return
	else:		
		ip_address = request.remote_addr
		requested_url = request.url
		referer_page = request.referrer
		page_name = request.path
		query_string = request.query_string
		user_agent = request.user_agent.string
				
		if config.track_session():
			log_id = session['log_id'] if 'log_id' in session else 0
			no_of_visits = session['no_of_visits']
			current_page = request.url
			previous_page = session['current_page'] if 'current_page' in session else ''
			
			if previous_page != current_page:
				
				log_visitor(ip_address, requested_url, referer_page, page_name, query_string, user_agent, no_of_visits)
		else:			
			conn = None
			cursor = None
			
			session.modified = True
			
			try:				
				conn = mysql.connect()
				cursor = conn.cursor()
				
				log_id = log_visitor(ip_address, requested_url, referer_page, page_name, query_string, user_agent)
				
				#print('log_id', log_id)
				
				if log_id > 0:				
					sql = 'select max(no_of_visits) as next from visits_log limit 1'
					
					conn = mysql.connect()
					cursor = conn.cursor(pymysql.cursors.DictCursor)
					
					cursor.execute(sql)
					row = cursor.fetchone()
					
					count = 0
					if row['next']:
						count += 1
					else:
						count = 1
					
					sql = 'UPDATE visits_log set no_of_visits = %s WHERE log_id = %s'
					data = (count, log_id,)
					
					cursor.execute(sql, data)
					
					conn.commit()
					
					session['track_session'] = True
					session['no_of_visits'] = count
					session['current_page'] = requested_url				
				else:
					session['track_session'] = False
			except Exception as e:
				print(e)
				session['track_session'] = False
			finally:
				cursor.close()
				conn.close()
				
def log_visitor(ip_address, requested_url, referer_page, page_name, query_string, user_agent, no_of_visits=None):
	sql = None
	data = None
	conn = None
	cursor = None
	log_id = 0
	
	if no_of_visits == None:
		sql = "INSERT INTO visits_log(no_of_visits, ip_address, requested_url, referer_page, page_name, query_string, user_agent) VALUES(%s, %s, %s, %s, %s, %s, %s)"
		data = (no_of_visits, ip_address, requested_url, referer_page, page_name, query_string, user_agent,)
	else:
		sql = "INSERT INTO visits_log(ip_address, requested_url, referer_page, page_name, query_string, user_agent) VALUES(%s, %s, %s, %s, %s, %s)"
		data = (ip_address, requested_url, referer_page, page_name, query_string, user_agent,)
	
	try:				
		conn = mysql.connect()
		cursor = conn.cursor()
		
		cursor.execute(sql, data)
		
		conn.commit()
		
		log_id = cursor.lastrowid
		
		return log_id
	except Exception as e:
		print(e)
	finally:
		cursor.close()
		conn.close()

Track Visitors

We have already created the required functionality to store information into database table. Now we will see how to track visitors when he/she visits your web pages.

Create a Python script main.py with the following source code.

import visitor
from app import app
from flask import jsonify	
	
@app.before_request
def do_something_when_a_request_comes_in():
	visitor.track_visitor()

@app.route('/')
def home():
	return jsonify({'msg' : 'hello'})

		
if __name__ == "__main__":
    app.run()

In the above Python script we have used a decorator from Flask API @app.before_request which will trigger your function when a request comes in your web page. So you don’t need to write a hook but Flask API already provides for you to use on application.

We have another function that returns simple hello message when you hit the URL http://localhost:5000.

This is a simple application that will track your visitors. To track referrer page you need to have more navigation on your website.

Testing the Application

Now navigate to the project directory and execute the command python main.py, your server will be started on default port 5000.

If you want to change the port then you can change the line app.run() to app.run(port=5001), where 5001 is the new port.

Now you can hit the URL http://localhost:5000 on your browser and you will see visitors details are logged into MySQL table.

You can see I have accessed this application few times from different browsers such as Chrome, FireFox, Internet Explorer in the below output from visits_log table.

python flask online visitors tracking system

As I have said earlier this application has only one URL and that’s why you won’t see value for referrer page for most of entries. You should have few navigations on your website and users should navigate from one page to another page then only you get proper value for referrer page column.

Now you can create a UI or front-end where you can track your visitors’ statistics on a graph.

Source Code

Download

Thanks for reading.

3 thoughts on “Python Flask Online Visitor Tracking System

  1. Hi and thank you for this usefull post.
    I want to implement this approach with sqlalchemy and postgre. but i have problem with solution when change code. could you help me please

Leave a Reply

Your email address will not be published. Required fields are marked *