Add sales automation stack: strategy docs, MCP scripts, PWA refinements
- 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
This commit is contained in:
Executable
+101
@@ -0,0 +1,101 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user