16 KiB
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 dataBacklinkServiceOrder— order tracking with marginAhrefsDomainSnapshot— DR, traffic, referring domains dataBacklinkIndexingRequest— indexing status tracking
Phase 2 Data Sources Available
Content(writer app) — articles published, word countsURLInspectionRecord+GSCMetricsCache(02C) — indexing status, search performanceSAGBacklink+CampaignKPISnapshot(02E) — backlink campaign metricsSocialPost+SocialEngagement(02H) — social media metricsSAGBlueprinthealth 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 renderingmatplotlib— chart generation (server-side SVG/PNG)
4. IMPLEMENTATION STEPS
Build Sequence
Week 1: Models + Report Engine
- Create
ServiceReport,AgencyBranding,ReportTemplatemodels + migration - Create serializers + viewsets
- Build
ReportService— metric collection from all 9 data sources - Build PDF template (base HTML + CSS) with section rendering
- Integrate WeasyPrint for HTML → PDF conversion
- Build chart generation via matplotlib (DR trend, traffic chart, etc.)
Week 2: White-Label + Dashboard
- Build
AgencyBrandingCRUD endpoints - Implement branding injection in report templates
- Build admin dashboard API endpoints
- Build Celery tasks for scheduled report generation
Week 3: Frontend
- Build
ServicesDashboard.tsx+ child components - Build
ClientDetail.tsx+ child components - Build
BacklinkOrders.tsx+IndexingDashboard.tsx - Build
ReportGenerator.tsx - Build client-facing
ManagedService/pages - Add sidebar items (admin + client conditional)
Zustand Stores
// 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_reportsemails generated-but-unsent reports- Pre-aggregation task collects metrics nightly for faster generation
White-Label Branding
AgencyBrandingstores name, logo, colors, contact info- When
is_white_label = True, "IGNY8"/"Alorig" replaced withbrand_name - Logo, colors, and footer text swapped in PDF output
- Multiple brandings supported per account
Admin Dashboard
ServicesDashboard.tsxshows all managed clients, MRR, revenueClientDetail.tsxshows config, content tracker, backlink tracker, reports, billingBacklinkOrders.tsxlists all orders filterable by client, status, packageIndexingDashboard.tsxshows indexing status across all clientsReportGenerator.tsxgenerates on-demand report for any client + period- Sidebar shows "Managed Services" link only for admin users
Client-Facing View
ServiceOverview.tsxshows tier, articles progress, current month statusReportViewer.tsxlists past reports with download linksApprovalQueue.tsxshows pending blueprint/content approvals- Sidebar shows "Managed Service" only when subscription exists
6. CLAUDE CODE INSTRUCTIONS
Context Requirements
- Read 04A (Managed Services) — subscription, order, Ahrefs, indexing models
- Read 02C (GSC Integration) — GSCMetricsCache, URLInspectionRecord for report sections
- Read 02E (Linker External) — SAGBacklink, CampaignKPISnapshot for backlink section
- Read 02H (Socializer) — SocialPost, SocialEngagement for social section
- Read 01G (SAG Health Monitoring) — health score for SAG section
- 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
- All IDs are integers — BigAutoField PKs
- Model names PLURAL — Clusters, Keywords, etc.
- Table prefix —
igny8_for all tables - App — models go in
servicesapp (same as 04A) - Frontend —
.tsxfiles, Zustand stores, infrontend/src/pages/Services/andfrontend/src/pages/ManagedService/ - Feature flag — admin dashboard behind
managed_services_enabledflag - Report data — always query by site + date range, never expose cross-account data
- PDF security — generated PDFs accessible only to account owner or admin
- Celery app —
igny8_corefor all tasks - New dependencies —
weasyprint,matplotlibadded torequirements.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 |