1
This commit is contained in:
393
v2/V2-Execution-Docs/04B-whitelabel-reporting.md
Normal file
393
v2/V2-Execution-Docs/04B-whitelabel-reporting.md
Normal file
@@ -0,0 +1,393 @@
|
||||
# IGNY8 Phase 4: White-Label & Reporting (04B)
|
||||
## Automated Reports, Agency Branding, Admin Dashboard, Client View
|
||||
|
||||
**Document Version:** 1.0
|
||||
**Date:** 2026-03-23
|
||||
**Phase:** IGNY8 Phase 4 — Business Layer
|
||||
**Status:** Build Ready
|
||||
**Source of Truth:** Codebase at `/data/app/igny8/`
|
||||
**Audience:** Claude Code, Backend Developers, Frontend Developers, Architects
|
||||
|
||||
---
|
||||
|
||||
## 1. CURRENT STATE
|
||||
|
||||
### No Reporting Infrastructure
|
||||
- Reports created manually by Alorig team via Google Docs/Sheets
|
||||
- No automated metric collection across IGNY8 modules
|
||||
- No PDF generation capability
|
||||
- No scheduled report delivery
|
||||
|
||||
### No Agency/Reseller Model
|
||||
- No white-label capability — all reports show IGNY8 branding
|
||||
- No custom branding configuration
|
||||
- No agency account structure
|
||||
|
||||
### Phase 4A Foundation Available (04A)
|
||||
- `ManagedServiceSubscription` — client subscription data
|
||||
- `BacklinkServiceOrder` — order tracking with margin
|
||||
- `AhrefsDomainSnapshot` — DR, traffic, referring domains data
|
||||
- `BacklinkIndexingRequest` — indexing status tracking
|
||||
|
||||
### Phase 2 Data Sources Available
|
||||
- `Content` (writer app) — articles published, word counts
|
||||
- `URLInspectionRecord` + `GSCMetricsCache` (02C) — indexing status, search performance
|
||||
- `SAGBacklink` + `CampaignKPISnapshot` (02E) — backlink campaign metrics
|
||||
- `SocialPost` + `SocialEngagement` (02H) — social media metrics
|
||||
- `SAGBlueprint` health score (01G) — SAG completion and authority
|
||||
- All IDs are integers (BigAutoField)
|
||||
|
||||
---
|
||||
|
||||
## 2. WHAT TO BUILD
|
||||
|
||||
### Overview
|
||||
An automated report generation engine with 9 configurable sections, PDF output, white-label branding for agencies, an admin services dashboard for Alorig, and a client-facing read-only view for managed service subscribers.
|
||||
|
||||
### Report Generation Engine
|
||||
|
||||
**9 Configurable Report Sections** (each can be included/excluded per client):
|
||||
|
||||
| # | Section | Data Sources |
|
||||
|---|---------|-------------|
|
||||
| 1 | **Executive Summary** | AI-generated from all other sections — key wins, KPI highlights |
|
||||
| 2 | **Content Performance** | `Content` model — articles published by type, word count, images created |
|
||||
| 3 | **Indexing Status** | `URLInspectionRecord` + `GSCMetricsCache` (02C) — indexed/pending/error trend |
|
||||
| 4 | **Keyword Rankings** | `GSCMetricsCache` (02C) + `AhrefsDomainSnapshot` (04A) — top 10/20/50, movers |
|
||||
| 5 | **Organic Traffic** | `GSCMetricsCache` (02C) — clicks, impressions, CTR, avg position, MoM change |
|
||||
| 6 | **Backlink Campaign** | `SAGBacklink` (02E) + `BacklinkServiceOrder` (04A) + `AhrefsDomainSnapshot` (04A) — links built, DR dist, budget, quality, referring domain growth |
|
||||
| 7 | **Social Media** | `SocialPost` + `SocialEngagement` (02H) — posts by platform, engagement, top performers |
|
||||
| 8 | **SAG Health** | `SAGBlueprint` (01G) — completion %, cluster status, authority score (0-100), content gaps |
|
||||
| 9 | **Next Month Plan** | `SAGCampaign` (02E) + automation queue — upcoming content topics, backlink targets, action items |
|
||||
|
||||
### PDF Report Generation
|
||||
|
||||
| Component | Choice | Rationale |
|
||||
|-----------|--------|-----------|
|
||||
| Template engine | WeasyPrint (HTML → PDF) | CSS-based layout, full typography control |
|
||||
| Charts | matplotlib (server-side rendering) | SVG/PNG charts embedded in HTML |
|
||||
| Storage | S3/media storage | URL saved in `ServiceReport.report_pdf_url` |
|
||||
| Themes | Light + Dark | Configurable per template |
|
||||
|
||||
**Report Flow:**
|
||||
```
|
||||
Celery task triggers → Collect metrics from all sources →
|
||||
Render section HTML per included sections →
|
||||
Generate charts via matplotlib → Merge into base template →
|
||||
WeasyPrint converts HTML → PDF → Upload to storage →
|
||||
Save ServiceReport with PDF URL → Email to recipients if configured
|
||||
```
|
||||
|
||||
### White-Label Branding (Agency Play)
|
||||
|
||||
For agencies reselling IGNY8 services:
|
||||
|
||||
**`AgencyBranding` provides:**
|
||||
- Agency name (replaces "IGNY8" / "Alorig" throughout PDF)
|
||||
- Logo URL (replaces IGNY8 logo in header)
|
||||
- Primary + secondary colors (brand color scheme)
|
||||
- Contact email + phone + website URL
|
||||
- Footer text
|
||||
|
||||
**When `ServiceReport.is_white_label = True`:**
|
||||
- All "IGNY8" and "Alorig" text replaced with `brand_name`
|
||||
- Logo swapped to `brand_logo_url`
|
||||
- Footer shows agency contact info
|
||||
- Color scheme uses agency brand colors
|
||||
- Report URL domain can be custom (via Caddy subdomain routing)
|
||||
|
||||
### Admin Services Dashboard (Alorig Team Only)
|
||||
|
||||
**Frontend Pages (.tsx + Zustand):**
|
||||
|
||||
```
|
||||
frontend/src/pages/Services/
|
||||
├── ServicesDashboard.tsx # Overview: all managed clients, MRR, revenue
|
||||
│ ├── ClientList.tsx # All subscriptions with status, tier, articles count
|
||||
│ ├── RevenueSummary.tsx # MRR total, margin total, trend chart
|
||||
│ └── UpcomingActions.tsx # Overdue: reports, content, renewals
|
||||
├── ClientDetail.tsx # Single client management
|
||||
│ ├── ClientConfig.tsx # Service config editor (JSON form)
|
||||
│ ├── ContentTracker.tsx # Articles published this month vs target
|
||||
│ ├── BacklinkTracker.tsx # Links ordered vs delivered vs live vs indexed
|
||||
│ ├── AhrefsMetrics.tsx # DR history, referring domains, top pages
|
||||
│ ├── ReportHistory.tsx # Past reports with resend option
|
||||
│ └── BillingHistory.tsx # Invoices, payments, margin per order
|
||||
├── BacklinkOrders.tsx # All orders across clients
|
||||
│ ├── OrderList.tsx # Filterable by client, status, package
|
||||
│ └── OrderDetail.tsx # Individual order with link-by-link tracking
|
||||
├── IndexingDashboard.tsx # Backlink indexing status across all clients
|
||||
└── ReportGenerator.tsx # Generate report for any client + period
|
||||
```
|
||||
|
||||
**Sidebar addition** (admin-only, behind `managed_services_enabled` feature flag):
|
||||
```
|
||||
ADMIN
|
||||
├── Sector Templates
|
||||
└── Managed Services (NEW)
|
||||
```
|
||||
|
||||
### Client-Facing View (Managed Service Subscribers)
|
||||
|
||||
For managed clients who also have IGNY8 SaaS access:
|
||||
|
||||
**Frontend Pages (.tsx + Zustand):**
|
||||
```
|
||||
frontend/src/pages/ManagedService/
|
||||
├── ServiceOverview.tsx # What's included, current month progress
|
||||
├── ReportViewer.tsx # View/download past reports
|
||||
└── ApprovalQueue.tsx # Approve blueprint, review content (if review_required)
|
||||
```
|
||||
|
||||
**Sidebar addition** (only shows if `ManagedServiceSubscription` exists for account):
|
||||
```
|
||||
ACCOUNT
|
||||
├── Account Settings
|
||||
├── Plans & Billing
|
||||
├── Managed Service (NEW — conditional)
|
||||
├── Usage
|
||||
└── AI Models
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. DATA MODELS & APIS
|
||||
|
||||
### New Models (in `services` app)
|
||||
|
||||
**`ServiceReport`** (extends `AccountBaseModel`)
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `site` | ForeignKey(Site) | Report target site |
|
||||
| `managed_subscription` | ForeignKey(ManagedServiceSubscription, null=True) | Linked subscription |
|
||||
| `report_type` | CharField(max_length=20) | `weekly` / `monthly` / `quarterly` |
|
||||
| `period_start` | DateField | Report period start |
|
||||
| `period_end` | DateField | Report period end |
|
||||
| `report_data` | JSONField | All metrics for period (structured by section) |
|
||||
| `report_pdf_url` | URLField(blank=True) | Generated PDF in S3 |
|
||||
| `is_white_label` | BooleanField(default=False) | Use agency branding |
|
||||
| `branding` | ForeignKey(AgencyBranding, null=True) | Agency branding reference |
|
||||
| `sections_included` | JSONField | List of included section keys |
|
||||
| `generated_at` | DateTimeField(auto_now_add=True) | Generation timestamp |
|
||||
| `sent_at` | DateTimeField(null=True) | Email sent timestamp |
|
||||
| `sent_to` | JSONField(default=list) | List of recipient emails |
|
||||
|
||||
Table: `igny8_service_reports`
|
||||
|
||||
**`AgencyBranding`** (extends `AccountBaseModel`)
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `brand_name` | CharField(max_length=200) | Agency name |
|
||||
| `brand_logo_url` | URLField(blank=True) | Logo URL |
|
||||
| `primary_color` | CharField(max_length=7) | Hex color code |
|
||||
| `secondary_color` | CharField(max_length=7) | Hex color code |
|
||||
| `contact_email` | EmailField(blank=True) | Agency contact email |
|
||||
| `contact_phone` | CharField(blank=True) | Agency phone |
|
||||
| `website_url` | URLField(blank=True) | Agency website |
|
||||
| `footer_text` | TextField(blank=True) | Custom footer text |
|
||||
| `is_active` | BooleanField(default=True) | Active flag |
|
||||
|
||||
Table: `igny8_agency_branding`
|
||||
|
||||
**`ReportTemplate`** (extends `AccountBaseModel`)
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `name` | CharField(max_length=200) | Template name |
|
||||
| `template_html` | TextField | Base HTML template |
|
||||
| `template_css` | TextField | Custom CSS |
|
||||
| `is_default` | BooleanField(default=False) | System default |
|
||||
| `branding` | ForeignKey(AgencyBranding, null=True) | Agency-specific template |
|
||||
|
||||
Table: `igny8_report_templates`
|
||||
|
||||
### API Endpoints
|
||||
|
||||
All under `/api/v1/`:
|
||||
|
||||
**Service Reports:**
|
||||
| Method | Endpoint | Purpose |
|
||||
|--------|----------|---------|
|
||||
| GET | `/services/reports/` | List (admin + client's own) |
|
||||
| POST | `/services/reports/generate/` | Generate report for site + period |
|
||||
| GET | `/services/reports/{id}/` | Detail + PDF URL |
|
||||
| POST | `/services/reports/{id}/send/` | Email to recipients |
|
||||
| POST | `/services/reports/{id}/regenerate/` | Regenerate PDF |
|
||||
| GET | `/services/reports/preview/` | Preview with data (no save) |
|
||||
|
||||
**Agency Branding:**
|
||||
| Method | Endpoint | Purpose |
|
||||
|--------|----------|---------|
|
||||
| GET | `/services/branding/` | List brandings |
|
||||
| POST | `/services/branding/` | Create branding |
|
||||
| GET | `/services/branding/{id}/` | Detail |
|
||||
| PUT | `/services/branding/{id}/` | Update |
|
||||
| DELETE | `/services/branding/{id}/` | Delete |
|
||||
|
||||
**Report Templates:**
|
||||
| Method | Endpoint | Purpose |
|
||||
|--------|----------|---------|
|
||||
| GET | `/services/report-templates/` | List templates |
|
||||
| POST | `/services/report-templates/` | Create custom template |
|
||||
| PUT | `/services/report-templates/{id}/` | Update template |
|
||||
|
||||
**Dashboard (Admin):**
|
||||
| Method | Endpoint | Purpose |
|
||||
|--------|----------|---------|
|
||||
| GET | `/services/dashboard/` | Revenue, clients, MRR |
|
||||
| GET | `/services/dashboard/overdue/` | Overdue deliverables |
|
||||
| GET | `/services/dashboard/margin/` | Margin tracking |
|
||||
| GET | `/services/dashboard/clients/` | Client list with status summary |
|
||||
|
||||
### Celery Tasks
|
||||
|
||||
| Task | Schedule | Purpose |
|
||||
|------|----------|---------|
|
||||
| `generate_weekly_reports` | Every Monday 6am | Generate for all Pro clients |
|
||||
| `generate_monthly_reports` | 1st of month | Generate for all Lite + Pro clients |
|
||||
| `send_pending_reports` | Daily | Email any generated but unsent reports |
|
||||
| `check_overdue_deliverables` | Daily | Flag clients behind on content/links |
|
||||
| `collect_report_metrics` | Nightly | Pre-aggregate metrics for faster generation |
|
||||
|
||||
### Services
|
||||
|
||||
| Service | Purpose |
|
||||
|---------|---------|
|
||||
| `ReportService` | `generate_report()` — collect metrics, render PDF |
|
||||
| `ReportEmailService` | Send report emails with PDF attachment or link |
|
||||
|
||||
### New Python Dependencies
|
||||
- `weasyprint` — HTML → PDF rendering
|
||||
- `matplotlib` — chart generation (server-side SVG/PNG)
|
||||
|
||||
---
|
||||
|
||||
## 4. IMPLEMENTATION STEPS
|
||||
|
||||
### Build Sequence
|
||||
|
||||
**Week 1: Models + Report Engine**
|
||||
1. Create `ServiceReport`, `AgencyBranding`, `ReportTemplate` models + migration
|
||||
2. Create serializers + viewsets
|
||||
3. Build `ReportService` — metric collection from all 9 data sources
|
||||
4. Build PDF template (base HTML + CSS) with section rendering
|
||||
5. Integrate WeasyPrint for HTML → PDF conversion
|
||||
6. Build chart generation via matplotlib (DR trend, traffic chart, etc.)
|
||||
|
||||
**Week 2: White-Label + Dashboard**
|
||||
1. Build `AgencyBranding` CRUD endpoints
|
||||
2. Implement branding injection in report templates
|
||||
3. Build admin dashboard API endpoints
|
||||
4. Build Celery tasks for scheduled report generation
|
||||
|
||||
**Week 3: Frontend**
|
||||
1. Build `ServicesDashboard.tsx` + child components
|
||||
2. Build `ClientDetail.tsx` + child components
|
||||
3. Build `BacklinkOrders.tsx` + `IndexingDashboard.tsx`
|
||||
4. Build `ReportGenerator.tsx`
|
||||
5. Build client-facing `ManagedService/` pages
|
||||
6. Add sidebar items (admin + client conditional)
|
||||
|
||||
### Zustand Stores
|
||||
|
||||
```typescript
|
||||
// frontend/src/stores/servicesStore.ts
|
||||
interface ServicesState {
|
||||
subscriptions: ManagedServiceSubscription[]
|
||||
reports: ServiceReport[]
|
||||
orders: BacklinkServiceOrder[]
|
||||
dashboard: DashboardSummary | null
|
||||
loading: boolean
|
||||
fetchSubscriptions: () => Promise<void>
|
||||
fetchReports: (siteId: number) => Promise<void>
|
||||
generateReport: (params: ReportParams) => Promise<void>
|
||||
fetchDashboard: () => Promise<void>
|
||||
}
|
||||
|
||||
// frontend/src/stores/brandingStore.ts
|
||||
interface BrandingState {
|
||||
brandings: AgencyBranding[]
|
||||
templates: ReportTemplate[]
|
||||
fetchBrandings: () => Promise<void>
|
||||
createBranding: (data: AgencyBrandingInput) => Promise<void>
|
||||
updateBranding: (id: number, data: AgencyBrandingInput) => Promise<void>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. ACCEPTANCE CRITERIA
|
||||
|
||||
### Report Generation
|
||||
- [ ] Reports generate with data from all 9 sections when data available
|
||||
- [ ] Sections configurable per client — excluded sections omitted from PDF
|
||||
- [ ] PDF renders correctly with charts, tables, and branding
|
||||
- [ ] WeasyPrint produces valid PDF files uploadable to S3
|
||||
- [ ] Charts render via matplotlib (DR trend, traffic chart, ranking distribution)
|
||||
- [ ] Generated PDF URL saved in `ServiceReport.report_pdf_url`
|
||||
|
||||
### Scheduled Reports
|
||||
- [ ] Weekly reports auto-generate on Monday 6am for all Pro clients
|
||||
- [ ] Monthly reports auto-generate on 1st for all Lite + Pro clients
|
||||
- [ ] `send_pending_reports` emails generated-but-unsent reports
|
||||
- [ ] Pre-aggregation task collects metrics nightly for faster generation
|
||||
|
||||
### White-Label Branding
|
||||
- [ ] `AgencyBranding` stores name, logo, colors, contact info
|
||||
- [ ] When `is_white_label = True`, "IGNY8"/"Alorig" replaced with `brand_name`
|
||||
- [ ] Logo, colors, and footer text swapped in PDF output
|
||||
- [ ] Multiple brandings supported per account
|
||||
|
||||
### Admin Dashboard
|
||||
- [ ] `ServicesDashboard.tsx` shows all managed clients, MRR, revenue
|
||||
- [ ] `ClientDetail.tsx` shows config, content tracker, backlink tracker, reports, billing
|
||||
- [ ] `BacklinkOrders.tsx` lists all orders filterable by client, status, package
|
||||
- [ ] `IndexingDashboard.tsx` shows indexing status across all clients
|
||||
- [ ] `ReportGenerator.tsx` generates on-demand report for any client + period
|
||||
- [ ] Sidebar shows "Managed Services" link only for admin users
|
||||
|
||||
### Client-Facing View
|
||||
- [ ] `ServiceOverview.tsx` shows tier, articles progress, current month status
|
||||
- [ ] `ReportViewer.tsx` lists past reports with download links
|
||||
- [ ] `ApprovalQueue.tsx` shows pending blueprint/content approvals
|
||||
- [ ] Sidebar shows "Managed Service" only when subscription exists
|
||||
|
||||
---
|
||||
|
||||
## 6. CLAUDE CODE INSTRUCTIONS
|
||||
|
||||
### Context Requirements
|
||||
1. Read 04A (Managed Services) — subscription, order, Ahrefs, indexing models
|
||||
2. Read 02C (GSC Integration) — GSCMetricsCache, URLInspectionRecord for report sections
|
||||
3. Read 02E (Linker External) — SAGBacklink, CampaignKPISnapshot for backlink section
|
||||
4. Read 02H (Socializer) — SocialPost, SocialEngagement for social section
|
||||
5. Read 01G (SAG Health Monitoring) — health score for SAG section
|
||||
6. Read existing billing app — understand existing admin sidebar structure
|
||||
|
||||
### Execution Order
|
||||
```
|
||||
Models + migrations → ReportService → PDF template + WeasyPrint →
|
||||
AgencyBranding CRUD → Celery tasks → Admin dashboard frontend → Client frontend
|
||||
```
|
||||
|
||||
### Critical Rules
|
||||
1. **All IDs are integers** — BigAutoField PKs
|
||||
2. **Model names PLURAL** — Clusters, Keywords, etc.
|
||||
3. **Table prefix** — `igny8_` for all tables
|
||||
4. **App** — models go in `services` app (same as 04A)
|
||||
5. **Frontend** — `.tsx` files, Zustand stores, in `frontend/src/pages/Services/` and `frontend/src/pages/ManagedService/`
|
||||
6. **Feature flag** — admin dashboard behind `managed_services_enabled` flag
|
||||
7. **Report data** — always query by site + date range, never expose cross-account data
|
||||
8. **PDF security** — generated PDFs accessible only to account owner or admin
|
||||
9. **Celery app** — `igny8_core` for all tasks
|
||||
10. **New dependencies** — `weasyprint`, `matplotlib` added to `requirements.txt`
|
||||
|
||||
### Cross-References
|
||||
|
||||
| Doc | Relationship |
|
||||
|-----|-------------|
|
||||
| 04A Managed Services | Subscription + order data feeds all reports |
|
||||
| 02C GSC Integration | GSCMetricsCache → sections 3 (Indexing), 4 (Rankings), 5 (Traffic) |
|
||||
| 02E Linker External | SAGBacklink + CampaignKPISnapshot → section 6 (Backlinks) |
|
||||
| 02H Socializer | SocialPost + SocialEngagement → section 7 (Social Media) |
|
||||
| 01G SAG Health Monitoring | Health score → section 8 (SAG Health) |
|
||||
| 04C Pricing Launch | Feature gates control who can access reports + white-label |
|
||||
Reference in New Issue
Block a user