a440160249
- SALES_STRATEGY.md: $1K/day plan (37 orders @ $27.50 AOV, 1,700 visits) - TRIPWIRE_FUNNEL.md: 7-email Mautic sequence + lead scoring - MONETIZATION.md: 9 monetization options for Nūr PWA (no ads, no registration) - EXECUTABLE_PLAN.md: MCP-executable automation plan - DAILY_OPS.md: daily KPI checklist (visits, orders, sends, recoveries) - scripts/: automation.py, mautic_setup.py, gumroad_setup.py, scout_scrape.py, analytics.py, crontab - quality_leads.json/.csv: 12 enriched Islamic-tech leads for Mautic import - content_queue.json: 10 SEO blog posts for Ghost - PWA: icons, sw.js, e2e + vitest coverage, generator scripts
101 lines
3.0 KiB
Python
Executable File
101 lines
3.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Daily Analytics Snapshot.
|
|
Captures revenue, orders, traffic, and KPIs.
|
|
Run via cron: 0 */6 * * * python scripts/analytics.py
|
|
"""
|
|
|
|
import os, sys, json, time
|
|
from datetime import datetime
|
|
|
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
METRICS_FILE = os.path.join(BASE_DIR, "daily_metrics.jsonl")
|
|
|
|
def log(msg):
|
|
print(f"[{datetime.now().isoformat()}] {msg}")
|
|
|
|
def append_metrics(**kwargs):
|
|
kwargs["timestamp"] = time.time()
|
|
kwargs["date"] = datetime.now().isoformat()[:10]
|
|
with open(METRICS_FILE, "a") as f:
|
|
f.write(json.dumps(kwargs) + "\n")
|
|
|
|
def get_gumroad_metrics():
|
|
"""Fetch revenue and orders from Gumroad."""
|
|
token = os.environ.get("GUMROAD_ACCESS_TOKEN", "")
|
|
if not token:
|
|
return {}
|
|
|
|
import requests
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
|
|
try:
|
|
r = requests.get(
|
|
"https://api.gumroad.com/v2/reports/overview",
|
|
headers=headers, timeout=10
|
|
)
|
|
if r.status_code == 200:
|
|
data = r.json()
|
|
return {
|
|
"gumroad_revenue": data.get("total_revenue", 0),
|
|
"gumroad_orders": data.get("total_sales", 0),
|
|
"gumroad_refunds": data.get("total_refunds", 0),
|
|
}
|
|
except Exception as e:
|
|
log(f"Gumroad API error: {e}")
|
|
|
|
return {}
|
|
|
|
def get_mautic_metrics():
|
|
"""Fetch email stats from Mautic."""
|
|
return {} # Placeholder — implement when Mautic API auth is fixed
|
|
|
|
def get_ghost_metrics():
|
|
"""Fetch blog traffic from Ghost."""
|
|
return {} # Placeholder — implement when Ghost API key is set
|
|
|
|
def main():
|
|
log("Analytics snapshot...")
|
|
|
|
metrics = {}
|
|
|
|
# Gumroad
|
|
metrics.update(get_gumroad_metrics())
|
|
|
|
# Calculate daily revenue (from last entry)
|
|
if os.path.exists(METRICS_FILE):
|
|
with open(METRICS_FILE) as f:
|
|
lines = f.readlines()
|
|
if len(lines) >= 2:
|
|
prev = json.loads(lines[-2])
|
|
curr = json.loads(lines[-1]) if lines else {}
|
|
rev_diff = curr.get("gumroad_revenue", 0) - prev.get("gumroad_revenue", 0)
|
|
metrics["daily_revenue"] = max(0, rev_diff)
|
|
metrics["daily_orders"] = max(0, curr.get("gumroad_orders", 0) - prev.get("gumroad_orders", 0))
|
|
|
|
# KPI check
|
|
daily_rev = metrics.get("daily_revenue", 0) / 100 # Convert cents to dollars
|
|
target = 1000
|
|
if daily_rev >= target:
|
|
metrics["kpi_status"] = "✅ HIT"
|
|
elif daily_rev >= target * 0.5:
|
|
metrics["kpi_status"] = "🟡 CLOSE"
|
|
else:
|
|
metrics["kpi_status"] = "🔴 BELOW"
|
|
|
|
metrics["kpi_target"] = target
|
|
metrics["kpi_actual"] = round(daily_rev, 2)
|
|
|
|
append_metrics(**metrics)
|
|
|
|
# Print summary
|
|
print(f"\n{'='*40}")
|
|
print(f" DAILY KPI SUMMARY")
|
|
print(f"{'='*40}")
|
|
print(f" Revenue: ${daily_rev:.2f} / ${target}")
|
|
print(f" Orders: {metrics.get('gumroad_orders', 0)}")
|
|
print(f" Status: {metrics.get('kpi_status', 'N/A')}")
|
|
print(f"{'='*40}\n")
|
|
|
|
if __name__ == "__main__":
|
|
main() |