Introduction
Ever wanted to track clicks on your affiliate links, monitor file downloads, or analyze outbound traffic from your Django application? If you've tried building this functionality from scratch, you know it quickly becomes complex when you need features like rate limiting, IP filtering, and geolocation.
Django-Clickify solves all these problems with a simple, powerful package that transforms any URL into a trackable link with just a few lines of code.
What is Django-Clickify?
Django-Clickify is a comprehensive click tracking solution for Django that logs every click on your tracked links, complete with IP address, user agent, timestamp, and even geographical location. It's perfect for:
- ๐ Affiliate Marketing: Track clicks on affiliate links
- ๐ File Downloads: Monitor who's downloading your content
- ๐ Outbound Links: Analyze external traffic patterns
- ๐ Campaign Analytics: Measure marketing campaign effectiveness
Key Features
- ๐ฏ Complete Click Tracking: IP address, user agent, timestamp, and more
- ๐ Automatic Geolocation: Country and city detection for each click
- ๐ก๏ธ Built-in Rate Limiting: Prevent abuse and bot traffic
- ๐ซ IP Filtering: Allowlists and blocklists for fine-grained control
- ๐ง Django Admin Integration: Manage links through familiar interface
- ๐ Dual Usage Modes: Template tags AND REST API support
- โก Production Ready: Handles proxies, load balancers, and CDNs
Installation & Setup
Step 1: Install the Package
# Basic installation
pip install django-clickify
# With all optional features (recommended)
pip install django-clickify[full]
# Or install specific features only
pip install django-clickify[ratelimit] # Rate limiting only
pip install django-clickify[drf] # API support only
Step 2: Configure Django Settings
Add to your INSTALLED_APPS
:
# settings.py
INSTALLED_APPS = [
# ... your other apps
'clickify',
'rest_framework', # Only if using API features
]
Step 3: Run Migrations
python manage.py migrate
This creates the database tables needed to store your tracked links and click data.
Basic Configuration
Django-Clickify works great out of the box, but here are the key settings you might want to customize:
# settings.py
# Geolocation (enabled by default)
CLICKIFY_GEOLOCATION = True
# Rate limiting (5 clicks per minute by default)
CLICKIFY_ENABLE_RATELIMIT = True
CLICKIFY_RATE_LIMIT = '5/m'
CLICKIFY_RATELIMIT_MESSAGE = "Too many requests. Please try again later."
# IP filtering
CLICKIFY_IP_ALLOWLIST = [] # Always allowed IPs
CLICKIFY_IP_BLOCKLIST = [] # Always blocked IPs
# For apps behind proxies/CDNs
CLICKIFY_IP_HEADERS = [
"HTTP_CF_CONNECTING_IP", # Cloudflare
"HTTP_X_FORWARDED_FOR", # Standard proxy
"HTTP_X_REAL_IP", # Nginx
"REMOTE_ADDR", # Fallback
]
Creating Your First Tracked Link
Using Django Admin
- Go to your Django Admin interface
- Navigate to the "Clickify" section
- Click "Add Tracked Link"
- Fill in the details:
-
Name:
Download Our App
-
Slug:
download-app
(auto-generated) -
Target URL:
https://play.google.com/store/apps/details?id=com.yourapp
-
Name:
That's it! Your tracked link is ready to use.
Usage Method 1: Template Tags (Traditional Django)
Perfect for server-rendered Django templates and most common use cases.
Step 1: Configure URLs
# urls.py
from django.urls import path, include
urlpatterns = [
# ... your other URLs
path('go/', include('clickify.urls', namespace='clickify')),
]
Step 2: Use in Templates
<!-- your_template.html -->
{% load clickify_tags %}
<div class="download-section">
<h2>Get Our Mobile App</h2>
<a href="{% track_url 'download-app' %}" class="btn btn-primary">
Download Now
</a>
</div>
<!-- Multiple tracked links -->
<div class="links">
<a href="{% track_url 'affiliate-product-1' %}">Special Offer 1</a>
<a href="{% track_url 'affiliate-product-2' %}">Special Offer 2</a>
<a href="{% track_url 'monthly-report-pdf' %}">Download Report</a>
</div>
Step 3: Handle Rate Limiting Messages
<!-- Display rate limiting messages -->
{% if messages %}
<div class="messages">
{% for message in messages %}
<div class="alert alert-{{ message.tags }}">
{{ message }}
</div>
{% endfor %}
</div>
{% endif %}
Usage Method 2: REST API (Modern JS Frameworks)
Perfect for React, Vue, Angular, or any JavaScript-heavy application.
Step 1: Configure API URLs
# urls.py
from django.urls import path, include
urlpatterns = [
# ... your other URLs
path('api/track/', include('clickify.drf_urls', namespace='clickify-api')),
]
Step 2: Track Clicks with JavaScript
// Modern async/await approach
async function trackClick(slug) {
try {
const response = await fetch(`/api/track/${slug}/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCsrfToken(), // Your CSRF token function
},
});
const data = await response.json();
if (response.ok) {
// Click tracked successfully
window.location.href = data.target_url;
} else {
// Handle rate limiting or other errors
alert(data.error);
}
} catch (error) {
console.error('Tracking failed:', error);
}
}
// Usage in your components
document.getElementById('download-btn').addEventListener('click', (e) => {
e.preventDefault();
trackClick('download-app');
});
React Component Example
// DownloadButton.jsx
import { useState } from 'react';
function DownloadButton({ slug, children }) {
const [isLoading, setIsLoading] = useState(false);
const handleClick = async (e) => {
e.preventDefault();
setIsLoading(true);
try {
const response = await fetch(`/api/track/${slug}/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCsrfToken(),
},
});
const data = await response.json();
if (response.ok) {
window.location.href = data.target_url;
} else {
alert(data.error);
}
} catch (error) {
console.error('Error:', error);
} finally {
setIsLoading(false);
}
};
return (
<button onClick={handleClick} disabled={isLoading}>
{isLoading ? 'Processing...' : children}
</button>
);
}
// Usage
<DownloadButton slug="download-app">
Download Our App
</DownloadButton>
Advanced Features
IP Filtering with Middleware
Enable sophisticated IP-based access control:
# settings.py
MIDDLEWARE = [
# ... other middleware
'clickify.middleware.IPFilterMiddleware',
# ... rest of middleware
]
# Configure IP filtering
CLICKIFY_IP_ALLOWLIST = ['192.168.1.100', '10.0.0.0/8']
CLICKIFY_IP_BLOCKLIST = ['192.168.1.50']
Custom Rate Limiting
Fine-tune rate limiting for your use case:
# settings.py
# Conservative: 2 clicks per hour
CLICKIFY_RATE_LIMIT = '2/h'
# Moderate: 10 clicks per minute
CLICKIFY_RATE_LIMIT = '10/m'
# Generous: 100 clicks per hour
CLICKIFY_RATE_LIMIT = '100/h'
# Disable rate limiting entirely
CLICKIFY_ENABLE_RATELIMIT = False
API Permission Control
Secure your tracking API:
# settings.py
CLICKIFY_PERMISSION_CLASSES = [
"rest_framework.permissions.IsAuthenticated"
]
# Custom exception handling for better API responses
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'clickify.drf_exception_handler.custom_exception_handler'
}
Real-World Example: E-commerce Affiliate Tracking
Let's build a complete affiliate link tracking system for an e-commerce site.
Step 1: Create Tracked Links in Admin
Create these tracked links:
-
Name:
Amazon Product 1
, Slug:amazon-product-1
-
Name:
eBay Special Deal
, Slug:ebay-special-deal
-
Name:
Shopify Partner Link
, Slug:shopify-partner
Step 2: Products Template
<!-- products.html -->
{% load clickify_tags %}
<div class="products-grid">
{% for product in products %}
<div class="product-card">
<img src="{{ product.image }}" alt="{{ product.name }}">
<h3>{{ product.name }}</h3>
<p class="price">${{ product.price }}</p>
<!-- Tracked affiliate link -->
<a href="{% track_url product.affiliate_slug %}"
class="btn btn-primary"
target="_blank">
Buy Now - Best Price!
</a>
</div>
{% endfor %}
</div>
<!-- Rate limiting message display -->
{% if messages %}
<div class="alert-container">
{% for message in messages %}
<div class="alert alert-warning">
{{ message }}
</div>
{% endfor %}
</div>
{% endif %}
Step 3: View Logic
# views.py
from django.shortcuts import render
def products_view(request):
products = [
{
'name': 'Wireless Headphones',
'price': 99.99,
'image': '/static/images/headphones.jpg',
'affiliate_slug': 'amazon-product-1'
},
{
'name': 'Smart Watch',
'price': 199.99,
'image': '/static/images/watch.jpg',
'affiliate_slug': 'ebay-special-deal'
},
]
return render(request, 'products.html', {'products': products})
Step 4: Analytics Dashboard
Access click analytics through Django Admin, or build a custom dashboard:
# analytics_views.py
from django.shortcuts import render
from clickify.models import TrackedLink, ClickLog
from django.db.models import Count
from django.utils import timezone
from datetime import timedelta
def analytics_dashboard(request):
# Get click stats for last 30 days
thirty_days_ago = timezone.now() - timedelta(days=30)
stats = ClickLog.objects.filter(
timestamp__gte=thirty_days_ago
).values(
'tracked_link__name'
).annotate(
click_count=Count('id')
).order_by('-click_count')
# Top countries
countries = ClickLog.objects.filter(
timestamp__gte=thirty_days_ago,
country__isnull=False
).values('country').annotate(
count=Count('id')
).order_by('-count')[:10]
context = {
'link_stats': stats,
'top_countries': countries,
'total_clicks': ClickLog.objects.filter(timestamp__gte=thirty_days_ago).count()
}
return render(request, 'analytics.html', context)
Production Deployment Tips
1. Geolocation Performance
For high-traffic sites, consider caching geolocation results:
# settings.py
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
}
}
2. Database Optimization
Add indexes for better query performance:
# In your custom migration or model
class Meta:
indexes = [
models.Index(fields=['timestamp']),
models.Index(fields=['ip_address']),
models.Index(fields=['tracked_link', 'timestamp']),
]
3. CDN and Proxy Configuration
For Cloudflare or AWS CloudFront:
# settings.py
CLICKIFY_IP_HEADERS = [
"HTTP_CF_CONNECTING_IP", # Cloudflare
"HTTP_X_FORWARDED_FOR", # AWS ALB/ELB
"HTTP_X_REAL_IP", # Nginx
"REMOTE_ADDR", # Fallback
]
Common Use Cases
1. Newsletter Link Tracking
Track which newsletter links get the most clicks:
{% load clickify_tags %}
<a href="{% track_url 'newsletter-cta-button' %}">Read Full Article</a>
2. Social Media Campaign Tracking
Create unique tracked links for each platform:
facebook-campaign-q4
twitter-promo-black-friday
instagram-story-link
3. File Download Analytics
Track PDF downloads, software downloads, etc.:
<a href="{% track_url 'whitepaper-download' %}" download>
Download Whitepaper (PDF)
</a>
4. A/B Testing Link Performance
Create two tracked links pointing to the same destination to test different call-to-action text.
Troubleshooting
Rate Limiting Not Working
Make sure you have django-ratelimit
installed:
pip install django-ratelimit
Geolocation Not Working
Check your internet connection and ensure the geolocation API is accessible.
API Permissions Issues
Verify your CLICKIFY_PERMISSION_CLASSES
setting and ensure proper authentication.
Missing Click Data
Check that your CLICKIFY_IP_HEADERS
are correctly configured for your deployment setup.
What Makes Django-Clickify Special?
Unlike simple URL shorteners or basic click counters, Django-Clickify provides:
- Enterprise-grade features out of the box
- Flexible deployment options (template tags + API)
- Built-in security (rate limiting, IP filtering)
- Rich analytics data (geolocation, user agents)
- Production-ready architecture
Whether you're running a small blog with affiliate links or a large e-commerce platform tracking millions of clicks, Django-Clickify scales to meet your needs.
Conclusion
Django-Clickify transforms the complex task of click tracking into a simple, powerful solution. With just a few lines of configuration, you get professional-grade analytics, security features, and flexible usage options.
The combination of template tags for traditional Django apps and REST API for modern JavaScript frameworks means you can use it in any Django project, regardless of your frontend architecture.
Get Started Today
- ๐ฆ Install:
pip install django-clickify[full]
- ๐ Documentation: Check the GitHub repository
- ๐ Source Code: GitHub
- ๐ PyPI Package: django-clickify on PyPI
Have you implemented click tracking in your Django projects? Share your experience and use cases in the comments below!
Top comments (0)