Integrated data pipeline and benchmarking platform for campaign risk assessment and performance analytics
Unified Northlight is a comprehensive platform that combines:
- Campaign Risk Assessment - Churn probability calculation and FLARE scoring for priority ranking
- Benchmarking System - Industry benchmark analysis for campaign performance
- ETL Pipeline - Automated data extraction from multiple sources (Corporate Portal, Salesforce)
- Real-time Monitoring - Pacing, utilization, and performance tracking
- Interactive Dashboards - Book management frontend with risk visualization
- 🎯 Account Priority Queue - Automatically ranks accounts by retention risk and business value
- 📊 Benchmark Tool - Compare campaign performance against industry standards
- 🔄 Automated ETL - Daily extraction and loading of 10+ data sources
- 📈 Risk Analytics - Advanced diagnostics with headline generation and waterfall visualization
- 🚨 Alert System - Proactive monitoring with JSONL-based alert tracking
- 🔍 Trajectory Analysis - Performance trend analysis and forecasting
- Quick Start
- Prerequisites
- Installation
- Configuration
- Running the Application
- ETL Pipeline
- API Documentation
- Project Structure
- Development
- Troubleshooting
- Contributing
# Clone the repository
git clone https://github.com/erinheit451/northlight2.git
cd northlight2
# Install dependencies
pip install -r requirements.txt
# Set up environment variables
cp .env.example .env
# Edit .env with your credentials
# Set up PostgreSQL database
createdb unified_northlight
# Run database migrations
python -m database.init.run_migrations
# Start the application
python main.py
# Visit http://localhost:4000- Python 3.8+ - Download
- PostgreSQL 13+ - Download
- Node.js 16+ (optional, for frontend development) - Download
- Corporate Portal - ReachLocal corporate portal access
- Salesforce - Salesforce account with MFA
- PostgreSQL - Database credentials
git clone https://github.com/erinheit451/northlight2.git
cd northlight2Option A: Using venv (recommended)
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activateOption B: Using conda
conda create -n northlight python=3.11
conda activate northlightpip install -r requirements.txtCore dependencies include:
- FastAPI + Uvicorn (API framework)
- SQLAlchemy + asyncpg (Database ORM)
- Playwright (Browser automation for extractors)
- Pandas (Data processing)
- Python-dotenv (Environment management)
Install Playwright browsers:
playwright install chromiumCreate database:
# Using psql
psql -U postgres
CREATE DATABASE unified_northlight;
CREATE USER northlight_user WITH PASSWORD 'your_secure_password';
GRANT ALL PRIVILEGES ON DATABASE unified_northlight TO northlight_user;
\qRun migrations:
python -m database.init.run_migrationsThis creates the required schemas:
heartbeat_core- Core campaign and performance dataheartbeat_performance- Performance metricsnorthlight_benchmarks- Benchmark data and standardsunified_analytics- Materialized views for analyticsbook- Book management data
Create a .env file in the root directory:
# Database Configuration
DATABASE_URL=postgresql+asyncpg://northlight_user:your_password@localhost:5432/unified_northlight
DATABASE_POOL_SIZE=20
DATABASE_MAX_OVERFLOW=30
# Corporate Portal Authentication
CORP_PORTAL_USERNAME=your.email@company.com
CORP_PORTAL_PASSWORD=your_password
CORP_PORTAL_URL=https://corp.reachlocal.com/common/logon.php
# Salesforce Authentication
SF_USERNAME=your.email@company.com
SF_PASSWORD=your_password
# SF_TOTP_CODE will be prompted interactively
# Application Configuration
API_HOST=0.0.0.0
API_PORT=4000
LOG_LEVEL=INFO.env to git. It's already in .gitignore.
core/config.py- Application settings and environment loadingdatabase/init/*.sql- Database schema definitions.gitignore- Excludes sensitive data, logs, and cache files
Development mode:
python main.pyProduction mode (with Gunicorn):
gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:4000The application will be available at:
- Dashboard: http://localhost:4000/
- Book Management: http://localhost:4000/book
- API Docs: http://localhost:4000/docs
- Health Check: http://localhost:4000/health
For convenience, use the provided batch files:
Start API Server:
# (Create a start_api.bat file or run python main.py directly)
python main.pyThe ETL pipeline extracts data from multiple sources, loads it into PostgreSQL, and runs transformations.
Corporate Portal (7 sources):
- Ultimate DMS Campaign Performance
- Budget Waterfall Client
- Budget Waterfall Channel
- Spend Revenue Performance
- DFP-RIJ (Down For Payment & Revenue In Jeopardy)
- Agreed CPL Performance
- BSC Standards
Salesforce (3 sources):
- Partner Pipeline
- Tim King Partner Pipeline
- Partner Calls
Complete ETL (Extract + Load + Transform):
# Windows
run_complete_etl.bat
# Linux/Mac
python scripts/runners/run_etl_pipeline.pyExtract Only:
# Windows
run_extractors.bat
# Linux/Mac
python scripts/runners/run_all_extractors.pyLoad Only (skip extraction):
python scripts/runners/run_etl_pipeline.py --skip-extractionBook Sync Only:
# Windows
sync_book.bat
# Linux/Mac
python scripts/run_book_sync.py- Database Setup - Ensure schemas and tables exist
- Data Extraction - Download CSV files from sources
- Data Loading - Load CSVs into PostgreSQL
- Analytics Refresh - Update materialized views
- Book Transformation - Transform data for book dashboard
- Book Schema Sync - Sync performance data to book tables
Set up Windows Task Scheduler:
# Run as Administrator
setup_scheduled_task.batThis creates a daily task that runs at 6:00 AM.
For Linux/Mac, use cron:
# Edit crontab
crontab -e
# Add daily ETL at 6 AM
0 6 * * * cd /path/to/northlight2 && /path/to/venv/bin/python scripts/runners/run_etl_pipeline.pyVisit http://localhost:4000/docs for interactive Swagger UI documentation.
Benchmarking:
GET /api/v1/benchmarks/meta- Get available benchmark categoriesPOST /api/v1/benchmarks/diagnose- Diagnose campaign performancePOST /api/v1/benchmarks/export/pptx- Export diagnosis as PowerPoint
Book Management:
GET /api/v1/book/summary- Get account summary statisticsGET /api/v1/book/accounts- List all accounts with filtersGET /api/v1/book/metadata- Get data freshness metadataGET /api/v1/book/partners/{partner}/advertisers- Get advertisers for partner
Trajectory Analysis:
GET /api/v1/trajectory/bulk- Get trajectory data for multiple campaigns
Health:
GET /health- Application health check
Currently, the API does not require authentication. For production deployment, consider adding:
- API keys
- OAuth2
- JWT tokens
unified-northlight/
├── main.py # FastAPI application entry point
├── requirements.txt # Python dependencies
├── README.md # This file
├── .env # Environment variables (create from .env.example)
├── .gitignore # Git ignore rules
│
├── api/ # API endpoints
│ └── v1/
│ ├── book.py # Book/account management API
│ ├── benchmarking.py # Benchmarking API
│ └── trajectory.py # Trajectory analysis API
│
├── core/ # Core application modules
│ ├── config.py # Configuration management
│ ├── database.py # Database connection and session management
│ ├── shared.py # Shared utilities (logging, etc.)
│ └── models/
│ └── book.py # SQLAlchemy models
│
├── book_risk_model/ # Risk scoring and assessment
│ ├── core/
│ │ ├── churn.py # Churn probability calculation
│ │ └── flare.py # FLARE scoring algorithm
│ ├── presentation/
│ │ └── diagnostics.py # Risk diagnostics and headline generation
│ ├── pg_ingest.py # PostgreSQL data ingestion
│ └── advertiser_lifetime.py # Advertiser lifetime value calculation
│
├── etl/ # ETL pipeline
│ └── unified/
│ └── data_loader.py # Unified data loader for all sources
│
├── extractors/ # Data extraction modules
│ ├── corp_portal/ # Corporate portal extractors
│ │ ├── ultimate_dms.py
│ │ ├── spend_revenue_performance.py
│ │ ├── bsc_standards.py
│ │ └── ... (7 extractors total)
│ ├── salesforce/ # Salesforce extractors
│ │ ├── partner_pipeline.py
│ │ ├── partner_calls.py
│ │ └── auth_enhanced.py # Salesforce authentication with MFA
│ └── monitor/
│ └── monitoring.py # Extraction monitoring and alerts
│
├── frontend/ # Frontend assets
│ ├── index.html # Main benchmarking tool
│ ├── unified-script.js # Benchmarking JavaScript
│ ├── styles.css # Global styles
│ └── book/
│ ├── index.html # Account priority dashboard
│ ├── script.js # Book dashboard logic
│ ├── trajectory.js # Trajectory visualization
│ └── risk_waterfall.js # Risk waterfall charts
│
├── scripts/ # Utility scripts
│ ├── runners/ # ETL orchestrators
│ │ ├── run_all_extractors.py
│ │ ├── run_etl_pipeline.py
│ │ └── run_complete_etl_sync.py
│ ├── check_book_data_freshness.py
│ ├── check_database_status.py
│ ├── sync_book_performance_data.py
│ └── transform_book_data.py
│
├── database/ # Database schemas and migrations
│ ├── init/
│ │ ├── 01_heartbeat_core.sql
│ │ ├── 02_heartbeat_performance.sql
│ │ ├── 03_benchmarks.sql
│ │ ├── 04_book_schema.sql
│ │ ├── 05_analytics.sql
│ │ └── 06_etl_tables.sql
│ └── migrations/
│
├── data/ # Data storage (not in git)
│ └── raw/ # Raw CSV files from extractors
│ ├── ultimate_dms/
│ ├── spend_revenue_performance/
│ ├── bsc_standards/
│ └── ... (10 source folders)
│
├── logs/ # Application logs (not in git)
│ ├── api.log
│ ├── etl.log
│ └── unified.log
│
└── alerts/ # Alert system (not in git)
└── alerts.jsonl
main.py - FastAPI application entry point. Configures routes, CORS, static files, and starts the server.
core/config.py - Centralized configuration using Pydantic settings. Loads from environment variables.
core/database.py - Database connection pooling, session management, and async context managers.
book_risk_model/ - Risk scoring algorithms including churn probability, FLARE scores, and diagnostic generation.
extractors/ - Browser automation scripts using Playwright to download data from Corporate Portal and Salesforce.
etl/unified/data_loader.py - Unified data loader that processes CSV files and loads them into PostgreSQL.
# Install dev dependencies
pip install -r requirements-dev.txt # (if exists)
# Or install common dev tools
pip install pytest black flake8 mypy# Run all tests
pytest
# Run with coverage
pytest --cov=. --cov-report=html
# Run specific test file
pytest tests/test_api.py# Format code with Black
black .
# Check linting with Flake8
flake8 .
# Type checking with mypy
mypy .When making schema changes:
- Create new SQL file in
database/init/ordatabase/migrations/ - Run migration:
python -m database.migrations.your_migration - Update models in
core/models/if needed
- Create extractor in
extractors/corp_portal/orextractors/salesforce/ - Add to
run_all_extractors.pyextractor list - Create corresponding loader in
etl/unified/data_loader.py - Update
DATABASE_INIT.mdwith new table schema
The frontend uses vanilla JavaScript (no build step required).
Files:
frontend/index.html- Benchmarking toolfrontend/book/index.html- Book dashboardfrontend/unified-script.js- Benchmarking logicfrontend/book/script.js- Book dashboard logic
Hot reload: FastAPI serves static files, so just refresh browser after changes.
1. Database connection errors
ERROR: could not connect to database
Solution: Check PostgreSQL is running and credentials in .env are correct.
# Test connection
psql -U northlight_user -d unified_northlight -h localhost2. Import errors
ModuleNotFoundError: No module named 'playwright'
Solution: Install dependencies and Playwright browsers.
pip install -r requirements.txt
playwright install chromium3. Extractor authentication failures
ERROR: MFA verification required
Solution: Run extractors interactively to enter MFA code. The code is cached for 24 hours.
python scripts/runners/run_all_extractors.py
# Enter MFA code when prompted4. Port already in use
ERROR: [Errno 48] Address already in use
Solution: Kill process on port 4000 or change port in .env.
# Find and kill process
lsof -ti:4000 | xargs kill -9 # Mac/Linux
netstat -ano | findstr :4000 # Windows (then taskkill /PID <pid> /F)5. Data not showing in dashboard
No accounts found / Empty dashboard
Solution: Run ETL pipeline to load data.
python scripts/runners/run_etl_pipeline.pyCheck logs for detailed error information:
- API logs:
logs/api.log - ETL logs:
logs/etl.log - Unified logs:
logs/unified.log - Alerts:
alerts/alerts.jsonl
Enable debug logging in .env:
LOG_LEVEL=DEBUGContributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests (
pytest) - Format code (
black .) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Python: PEP 8 (use Black formatter)
- JavaScript: Standard JS style
- SQL: Uppercase keywords, snake_case identifiers
- Comments: Docstrings for all functions/classes
This project is proprietary software. All rights reserved.
For questions or issues:
- Check the Troubleshooting section
- Review logs in
logs/directory - Open an issue on GitHub
- Contact the development team
Corporate Portal / Salesforce
↓
Extractors (Playwright)
↓
data/raw/*.csv
↓
ETL Data Loader
↓
PostgreSQL Database
↓
FastAPI Endpoints
↓
Frontend Dashboard
- Backend: FastAPI + Python 3.11
- Database: PostgreSQL 15 with asyncpg
- ORM: SQLAlchemy (async)
- Extractors: Playwright (browser automation)
- Frontend: Vanilla JavaScript + HTML5 + CSS3
- Data Processing: Pandas + NumPy
- Logging: Python logging module
- Alerts: JSONL format
- Credentials: Stored in
.env(never committed to git) - Database: Use strong passwords and connection pooling
- API: Consider adding authentication for production
- MFA: Salesforce extractors support TOTP-based MFA
- Logs: Contain no sensitive information (credentials redacted)
See CHANGELOG.md for version history and release notes.
Built with ❤️ for campaign performance optimization