feat: added desktop sso endpoints
This commit is contained in:
61
vibn-attribution-package/backend/mixins.py
Normal file
61
vibn-attribution-package/backend/mixins.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import logging
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class VibnAttributionCaptureMixin:
|
||||
"""
|
||||
A Django REST Framework ViewSet/APIView mixin that automatically
|
||||
extracts marketing attribution fields (UTMs, referrer) from incoming
|
||||
request payloads or HTTP headers and binds them to the saving object.
|
||||
|
||||
Compatible with any Django REST Framework serializer.
|
||||
"""
|
||||
|
||||
def extract_attribution_data(self, request):
|
||||
"""
|
||||
Extracts UTM and referrer keys from request data, falling back
|
||||
to request headers if required.
|
||||
"""
|
||||
# Try request payload first
|
||||
data = request.data or {}
|
||||
|
||||
utm_source = data.get("utm_source")
|
||||
utm_medium = data.get("utm_medium")
|
||||
utm_campaign = data.get("utm_campaign")
|
||||
utm_content = data.get("utm_content")
|
||||
utm_term = data.get("utm_term")
|
||||
|
||||
# Capture Referrer from payload or fallback to HTTP headers
|
||||
referrer = data.get("referrer")
|
||||
if not referrer:
|
||||
referrer = request.META.get("HTTP_REFERER")
|
||||
|
||||
return {
|
||||
"utm_source": utm_source,
|
||||
"utm_medium": utm_medium,
|
||||
"utm_campaign": utm_campaign,
|
||||
"utm_content": utm_content,
|
||||
"utm_term": utm_term,
|
||||
"referrer": referrer,
|
||||
}
|
||||
|
||||
def perform_create(self, serializer):
|
||||
"""
|
||||
In DRF ViewSets, overrides perform_create to automatically inject
|
||||
attribution fields directly into the saved model instance.
|
||||
"""
|
||||
attrib_data = self.extract_attribution_data(self.request)
|
||||
|
||||
# Save serializer with attribution params injected as overrides
|
||||
instance = serializer.save(
|
||||
**{k: v for k, v in attrib_data.items() if v is not None}
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"VibnTracker: Saved attribution data to {instance.__class__.__name__} "
|
||||
f"(Source: {attrib_data['utm_source']}, Campaign: {attrib_data['utm_campaign']})"
|
||||
)
|
||||
return instance
|
||||
164
vibn-attribution-package/backend/models.py
Normal file
164
vibn-attribution-package/backend/models.py
Normal file
@@ -0,0 +1,164 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class VibnAbstractAttributionModel(models.Model):
|
||||
"""
|
||||
An abstract Django model that adds standard marketing attribution
|
||||
(first-touch UTM parameters & referrers) to any model (e.g. User, APIClient, Customer).
|
||||
|
||||
To implement:
|
||||
class APIClient(VibnAbstractAttributionModel):
|
||||
name = models.CharField(max_length=255)
|
||||
# ... other fields ...
|
||||
"""
|
||||
|
||||
utm_source = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Marketing channel source (e.g. twitter, google, newsletter)",
|
||||
)
|
||||
utm_medium = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Marketing medium (e.g. cpc, social, organic, email)",
|
||||
)
|
||||
utm_campaign = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Marketing campaign name (e.g. mcp-launch, spring-discount)",
|
||||
)
|
||||
utm_content = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Specific content links or ad identifiers clicked",
|
||||
)
|
||||
utm_term = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Keywords searched or paid terms clicked",
|
||||
)
|
||||
referrer = models.CharField(
|
||||
max_length=1000,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="First-touch browser referrer URL (e.g. https://t.co/, https://google.com)",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def save_attribution(
|
||||
self,
|
||||
utm_source,
|
||||
utm_medium=None,
|
||||
utm_campaign=None,
|
||||
utm_content=None,
|
||||
utm_term=None,
|
||||
referrer=None,
|
||||
overwrite=False,
|
||||
):
|
||||
"""
|
||||
Helper method to securely save marketing attribution data if it hasn't been set yet.
|
||||
"""
|
||||
if overwrite or not self.utm_source:
|
||||
self.utm_source = utm_source
|
||||
self.utm_medium = utm_medium
|
||||
self.utm_campaign = utm_campaign
|
||||
self.utm_content = utm_content
|
||||
self.utm_term = utm_term
|
||||
self.referrer = referrer
|
||||
self.save(
|
||||
update_fields=[
|
||||
"utm_source",
|
||||
"utm_medium",
|
||||
"utm_campaign",
|
||||
"utm_content",
|
||||
"utm_term",
|
||||
"referrer",
|
||||
]
|
||||
if self.pk
|
||||
else None
|
||||
)
|
||||
|
||||
|
||||
class VibnPageview(models.Model):
|
||||
"""
|
||||
Vibn Pageview Tracking Model.
|
||||
Tracks active user interactions and page loads in real-time,
|
||||
providing fully dynamic traffic data and click timelines.
|
||||
"""
|
||||
|
||||
user = models.ForeignKey(
|
||||
"UserProfile", # Replace with your custom User model name
|
||||
on_delete=models.CASCADE,
|
||||
related_name="pageviews",
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
session_id = models.CharField(
|
||||
max_length=255, db_index=True, help_text="Unique browser session tracker ID"
|
||||
)
|
||||
url_path = models.CharField(
|
||||
max_length=500, db_index=True, help_text="Tracked page path, e.g. /pricing"
|
||||
)
|
||||
referrer = models.CharField(
|
||||
max_length=1000, null=True, blank=True, help_text="Traffic referrer URL"
|
||||
)
|
||||
|
||||
# Captured UTM variables
|
||||
utm_source = models.CharField(max_length=255, null=True, blank=True)
|
||||
utm_medium = models.CharField(max_length=255, null=True, blank=True)
|
||||
utm_campaign = models.CharField(max_length=255, null=True, blank=True)
|
||||
utm_content = models.CharField(max_length=255, null=True, blank=True)
|
||||
utm_term = models.CharField(max_length=255, null=True, blank=True)
|
||||
|
||||
# Device/Geo details
|
||||
device = models.CharField(max_length=100, default="desktop")
|
||||
browser = models.CharField(max_length=100, default="chrome")
|
||||
country = models.CharField(max_length=100, default="US")
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
|
||||
|
||||
class Meta:
|
||||
db_table = "vibn_pageview"
|
||||
verbose_name = "Vibn Pageview"
|
||||
verbose_name_plural = "Vibn Pageviews"
|
||||
ordering = ["-created_at"]
|
||||
|
||||
|
||||
class VibnEvent(models.Model):
|
||||
"""
|
||||
Vibn Product Event Tracking Model.
|
||||
Tracks custom user conversion events (e.g. signup, connect_channel, create_campaign)
|
||||
and binds them to their sessions and profiles.
|
||||
"""
|
||||
|
||||
user = models.ForeignKey(
|
||||
"UserProfile", # Replace with your custom User model name
|
||||
on_delete=models.CASCADE,
|
||||
related_name="events",
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
session_id = models.CharField(max_length=255, db_index=True)
|
||||
event_name = models.CharField(
|
||||
max_length=255,
|
||||
db_index=True,
|
||||
help_text="Custom event name, e.g. connect_social",
|
||||
)
|
||||
properties = models.JSONField(
|
||||
default=dict, blank=True, help_text="Custom event properties JSON"
|
||||
)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
|
||||
|
||||
class Meta:
|
||||
db_table = "vibn_event"
|
||||
verbose_name = "Vibn Event"
|
||||
verbose_name_plural = "Vibn Events"
|
||||
ordering = ["-created_at"]
|
||||
Reference in New Issue
Block a user