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"]