feat: added desktop sso endpoints
This commit is contained in:
226
vibn-attribution-package/README.md
Normal file
226
vibn-attribution-package/README.md
Normal file
@@ -0,0 +1,226 @@
|
||||
# 🚀 Vibn Marketing Attribution & Identity Sync SDK
|
||||
|
||||
A modular, highly scalable, and decoupled SDK package to link anonymous site traffic tracking (**Umami Analytics**) with registered user profiles (**Vibn Database**), providing comprehensive **First-Touch Marketing Attribution** and acquisition logs.
|
||||
|
||||
Developed originally for **Missinglettr** and structured specifically to be drop-in ready for the **Vibn Platform** architecture.
|
||||
|
||||
---
|
||||
|
||||
## 📁 Package Inventory
|
||||
|
||||
This package contains three decoupled layers designed to be copied directly into your respective repositories:
|
||||
|
||||
| Path | Purpose | Language / Framework |
|
||||
| :--- | :--- | :--- |
|
||||
| `frontend/VibnTracker.tsx` | Client-side search params listener, sessionStorage / Cookie persistence, automated Umami injection, and session identity bridging (`identify()`). | TypeScript / Next.js React |
|
||||
| `backend/models.py` | Abstract Base Django Model adding UTM and Referrer fields to any User / Client record. | Python / Django |
|
||||
| `backend/mixins.py` | Django REST Framework (DRF) interceptor mixin to auto-capture attribution variables from incoming signup payloads. | Python / Django REST Framework |
|
||||
| `umami-bridge/umami_service.py` | Reusable bridge to pull aggregated pageviews, session timestamps, and raw click-trails from Umami (via REST API or raw DB joins). | Python / Django |
|
||||
|
||||
---
|
||||
|
||||
## 🏛️ Architecture Overview
|
||||
|
||||
The system bridges anonymous traffic with database records using a secure **Identity Exchange**:
|
||||
|
||||
```
|
||||
[Anonymous Visitor Clicks Ad / Tweet]
|
||||
│
|
||||
▼
|
||||
[Lands on Website with UTMs & Referrer]
|
||||
│ ├── Auto-logged in Umami (analytics.vibnai.com)
|
||||
│ └── Cached client-side in sessionStorage & Cookie fallback
|
||||
▼
|
||||
[Signs Up / Logs in via Google OAuth]
|
||||
│
|
||||
▼
|
||||
[Frontend POSTs Signup payload + UTM params to Backend]
|
||||
│
|
||||
▼
|
||||
[Django Backend saves user record + permanently binds UTM columns]
|
||||
│
|
||||
▼
|
||||
[Frontend calls useVibnTracker.identify(user_id)]
|
||||
│
|
||||
▼
|
||||
[Umami merges ALL previous anonymous browsing history with this new User ID!]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💻 Step-by-Step Implementation Guide
|
||||
|
||||
### 1. Frontend Integration (Vibn Next.js Web App)
|
||||
|
||||
Copy `frontend/VibnTracker.tsx` into your Next.js project (e.g., inside `components/metrics/VibnTracker.tsx`):
|
||||
|
||||
#### A. Wrap your Root Layout:
|
||||
In `app/layout.tsx` (or your entry file), wrap the tree with `VibnTrackerProvider`. This will automatically inject your Umami tracking script and listen for UTM parameters across your landing and console domains:
|
||||
|
||||
```tsx
|
||||
import { VibnTrackerProvider } from "@/components/metrics/VibnTracker";
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<VibnTrackerProvider
|
||||
umamiWebsiteId="your-umami-website-uuid"
|
||||
umamiScriptUrl="https://analytics.vibnai.com/script.js"
|
||||
>
|
||||
<body>{children}</body>
|
||||
</VibnTrackerProvider>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### B. Capture & Send on Signup / Google OAuth exchange:
|
||||
In your signup or Google OAuth exchange page (where the user completes registration), extract the cached attribution parameters using the `useVibnTracker` hook and send them in the request body to your backend:
|
||||
|
||||
```tsx
|
||||
import { useVibnTracker } from "@/components/metrics/VibnTracker";
|
||||
|
||||
export default function GoogleCallbackPage() {
|
||||
const { getStoredAttribution, identify, track } = useVibnTracker();
|
||||
|
||||
const handleOAuthSignup = async (googleToken: string) => {
|
||||
// 1. Get first-touch parameters cached in browser
|
||||
const attribution = getStoredAttribution();
|
||||
|
||||
// 2. POST to your register endpoint
|
||||
const response = await fetch("/api/auth/register", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
google_token: googleToken,
|
||||
...attribution // Sends utm_source, utm_medium, utm_campaign, referrer, etc.
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const user = await response.json();
|
||||
|
||||
// 3. BRIDGING IDENTITY: Link anonymous browser history with real user ID!
|
||||
identify({
|
||||
userId: user.id, // Primary key in your database
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
plan: user.plan
|
||||
});
|
||||
|
||||
// 4. Track custom sign-up conversion in Umami
|
||||
track("user_completed_signup", { plan: user.plan });
|
||||
}
|
||||
};
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Backend Integration (Vibn Django API)
|
||||
|
||||
Copy `backend/models.py` and `backend/mixins.py` into your Django apps.
|
||||
|
||||
#### A. Inherit from the Abstract Model:
|
||||
Add first-touch marketing attribution columns to your active User or APIClient model by inheriting from `VibnAbstractAttributionModel`:
|
||||
|
||||
```python
|
||||
# your_app/models.py
|
||||
from backend.models import VibnAbstractAttributionModel
|
||||
|
||||
class UserProfile(VibnAbstractAttributionModel):
|
||||
# Your existing fields
|
||||
email = models.EmailField(unique=True)
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
class Meta:
|
||||
db_table = "user_profile"
|
||||
```
|
||||
|
||||
Then generate and apply your database migrations:
|
||||
```bash
|
||||
python manage.py makemigrations
|
||||
python manage.py migrate
|
||||
```
|
||||
|
||||
#### B. Intercept requests with the DRF View Mixin:
|
||||
Add the `VibnAttributionCaptureMixin` to your Signup or Authentication API ViewSet. It will automatically intercept, extract, and write the UTM parameters into the saving model:
|
||||
|
||||
```python
|
||||
# your_app/views.py
|
||||
from rest_framework import viewsets
|
||||
from backend.mixins import VibnAttributionCaptureMixin
|
||||
from .models import UserProfile
|
||||
from .serializers import UserProfileSerializer
|
||||
|
||||
class RegisterViewSet(VibnAttributionCaptureMixin, viewsets.ModelViewSet):
|
||||
"""
|
||||
User registration API view.
|
||||
VibnAttributionCaptureMixin automatically grabs utm_source, utm_campaign,
|
||||
and Referrer headers from requests and binds them onto the UserProfile on save.
|
||||
"""
|
||||
queryset = UserProfile.objects.all()
|
||||
serializer_class = UserProfileSerializer
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Expose Live Traffic Trails in Admin Consoles
|
||||
|
||||
Copy `umami-bridge/umami_service.py` into your Python services.
|
||||
|
||||
You can securely query stats directly from your Umami self-hosted database (read-only) inside your Admin panels, allowing you to render **actual pageviews, device breakdowns, and exact visitor session timelines** for any specific client.
|
||||
|
||||
#### A. Configure Umami DB Connection:
|
||||
In Django's `settings.py`, register your Umami database:
|
||||
|
||||
```python
|
||||
DATABASES = {
|
||||
'default': {
|
||||
# Your main application DB
|
||||
},
|
||||
'umami_db': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': 'umami_production_db',
|
||||
'USER': 'readonly_user',
|
||||
'PASSWORD': 'password',
|
||||
'HOST': '34.19.250.135',
|
||||
'PORT': '5432',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### B. Fetch Live Session Data for Admin Console:
|
||||
In your Admin API view (e.g. `admin_user_detail`), call the service to fetch raw click-trails:
|
||||
|
||||
```python
|
||||
# your_admin_app/views.py
|
||||
from rest_framework.response import Response
|
||||
from umami_bridge.umami_service import VibnUmamiService
|
||||
|
||||
def get_admin_user_profile(request, user_id):
|
||||
# Initialize service
|
||||
umami = VibnUmamiService()
|
||||
|
||||
# 1. Fetch total web sessions, total pageviews, and first interaction timestamp
|
||||
funnel = umami.get_aggregated_funnel_for_user(user_id, db_connection_name="umami_db")
|
||||
|
||||
# 2. Fetch the actual 50 most recent page clicks, devices, and browsers used by this client!
|
||||
click_trail = umami.get_user_session_click_trail(user_id, db_connection_name="umami_db")
|
||||
|
||||
return Response({
|
||||
"user_id": user_id,
|
||||
"first_touch_web_funnel": funnel,
|
||||
"live_click_trail": click_trail
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ Best Practices & GDPR Compliance
|
||||
|
||||
1. **Self-Hosted Privacy:** Because Umami is hosted on your domain (`analytics.vibnai.com`), cookie and script blockades are minimized, and no data is shared with third parties (complying strictly with GDPR, CCPA, and PECR).
|
||||
2. **First-Touch Preservation:** The mixin uses `if not client.utm_source:` checks on save, ensuring first-touch parameters (the exact ad or link that *originally* brought the user in) are preserved and never overwritten by subsequent organic logins.
|
||||
3. **No Database Blockades:** The `umami_service.py` uses read-only connections and limits queries to `LIMIT 50` to make sure raw analytics querying never causes performance blocks on your main application database thread.
|
||||
Reference in New Issue
Block a user