#!/usr/bin/env python3 """ Marketing-SEO Agent v2 - With GA4 Integration 24/7 Monitoring: Site Uptime + Traffic Analytics """ import json import time import urllib.request from datetime import datetime from pathlib import Path from google.analytics.data import BetaAnalyticsDataClient from google.analytics.data_v1beta.types import RunReportRequest, DateRange, Metric WORKSPACE = Path(__file__).parent.parent LOG_DIR = WORKSPACE / "logs" STATE_FILE = WORKSPACE / "state" / "agent-state.json" CONFIG_DIR = WORKSPACE / "config" GA_CREDS = CONFIG_DIR / "ga-credentials.json" GA_PROPERTY = "526394825" SITES = [ "https://www.hoaledgeriq.com", "https://app.hoaledgeriq.com" ] MONITOR_INTERVAL = 3600 LOG_DIR.mkdir(parents=True, exist_ok=True) def log(msg): ts = datetime.now().strftime('%Y-%m-%d %H:%M:%S') line = f"[{ts}] {msg}" print(line) log_file = LOG_DIR / f"seo-agent-{datetime.now().strftime('%Y%m%d')}.log" with open(log_file, 'a') as f: f.write(line + '\n') def check_site(url): """Check if site is up""" start = time.time() try: req = urllib.request.Request(url, headers={"User-Agent": "SEO-Agent/1.0"}) with urllib.request.urlopen(req, timeout=15) as r: return r.getcode() == 200, r.getcode(), round(time.time() - start, 2) except Exception as e: return False, str(e), None def get_ga4_data(): """Get GA4 traffic data""" try: client = BetaAnalyticsDataClient.from_service_account_json(str(GA_CREDS)) request = RunReportRequest( property=f"properties/{GA_PROPERTY}", date_ranges=[DateRange(start_date="1daysAgo", end_date="today")], metrics=[ Metric(name="sessions"), Metric(name="activeUsers"), Metric(name="newUsers"), Metric(name="bounceRate"), Metric(name="averageSessionDuration") ] ) response = client.run_report(request) if response.rows: r = response.rows[0] return { "sessions": int(r.metric_values[0].value), "users": int(r.metric_values[1].value), "new_users": int(r.metric_values[2].value), "bounce_rate": float(r.metric_values[3].value), "avg_duration": float(r.metric_values[4].value) } except Exception as e: return {"error": str(e)} return {"sessions": 0, "users": 0, "new_users": 0} def send_alert(title, message, severity="warning"): """Send Telegram alert""" log(f"šŸ”” ALERT [{severity}]: {title}") try: tg_msg = f"šŸ”” *SEO Alert: {title}*\n\n{message}\n\nā° {datetime.now().strftime('%H:%M')}" subprocess.run(["openclaw", "message", "send", "--text", tg_msg], capture_output=True, timeout=10) except: pass def hourly_check(): """Hourly monitoring: Sites + GA4""" log("=== Hourly Site + Traffic Check ===") site_status = {} for site in SITES: is_up, status, time_ms = check_site(site) site_status[site] = {"up": is_up, "status": status, "time_ms": time_ms} if is_up: log(f"āœ… {site}: UP ({status}) - {time_ms}s") else: log(f"āŒ {site}: DOWN ({status})") send_alert(f"SITE DOWN: {site}", f"Status: {status}", "critical") # GA4 traffic ga = get_ga4_data() if "error" not in ga: log(f"šŸ“Š GA4 Traffic: {ga.get('sessions',0)} sessions, {ga.get('users',0)} users") else: log(f"āš ļø GA4 Error: {ga.get('error')}") return {"sites": site_status, "ga4": ga} def main(): log("šŸš€ Marketing-SEO Agent v2 Started") log(f"Sites: {', '.join(SITES)}") log(f"GA4 Property: {GA_PROPERTY}") last_check = 0 while True: now = datetime.now() now_ts = int(now.timestamp()) if now_ts - last_check >= MONITOR_INTERVAL: hourly_check() last_check = now_ts time.sleep(60) if __name__ == "__main__": main() def daily_rank_check(): """Daily check - if any keywords break into top 100, alert""" import re state_file = WORKSPACE / "state" / "rank-data.json" if not state_file.exists(): return with open(state_file) as f: data = json.load(f) positions = data.get('positions', {}) # Check if any are now ranked (non-null) ranked = sum(1 for p in positions.values() if p is not None) total = len(positions) if ranked > 0: log(f"šŸ“ˆ Rank Progress: {ranked}/{total} keywords now ranking") # Alert on new rankings report = "šŸŽ‰ *RANKING PROGRESS!*\n\n" for kw, pos in positions.items(): if pos: report += f"• {kw}: #{pos}\n" send_alert("New Rankings Detected!", report, "info") else: log(f"šŸ“Š SEO Status: ({ranked}/{total} keywords in top 100 - baseline phase)") def get_monthly_milestone(): """Return current SEO milestone based on launch date""" launch = datetime(2026, 3, 22) # Launch date now = datetime.now() days_live = (now - launch).days if days_live < 30: return "Month 1: Focus on technical SEO + content creation" elif days_live < 90: return "Month 2-3: Target long-tail keywords, build backlinks" elif days_live < 180: return "Month 4-6: Optimize for primary keywords" else: return "Phase 2: Established - maintenance + expansion" # Add to daily check