Files
igny8/v2/V2-Execution-Docs/04B-whitelabel-reporting.md
IGNY8 VPS (Salman) 0570052fec 1
2026-03-23 17:20:51 +00:00

394 lines
16 KiB
Markdown

# 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 |