#!/usr/bin/env python3 import json import os import sys from datetime import date, timedelta from google.oauth2.credentials import Credentials from googleapiclient.discovery import build def get_creds(): token_path = "/root/.hermes/profiles/reviewer/google_token.json" if not os.path.exists(token_path): token_path = os.path.expanduser("~/.hermes/google_token.json") if not os.path.exists(token_path): print("Error: Google token file not found.") sys.exit(1) with open(token_path, "r") as f: token_data = json.load(f) return Credentials.from_authorized_user_info(token_data) def main(): creds = get_creds() analytics = build('analyticsdata', 'v1beta', credentials=creds) gsc = build('searchconsole', 'v1', credentials=creds) site_url = 'https://www.greenleafvietnam.com/' property_id = 'properties/481665400' # Date ranges today = date.today() cur_to = today - timedelta(days=1) cur_from = today - timedelta(days=30) prev_to = today - timedelta(days=31) prev_from = today - timedelta(days=60) cur_to_str = cur_to.isoformat() cur_from_str = cur_from.isoformat() prev_to_str = prev_to.isoformat() prev_from_str = prev_from.isoformat() print(f"Current period: {cur_from_str} to {cur_to_str}") print(f"Previous period: {prev_from_str} to {prev_to_str}") data = { "site_url": site_url, "property_id": property_id, "current_period": {"from": cur_from_str, "to": cur_to_str}, "previous_period": {"from": prev_from_str, "to": prev_to_str}, } # 1. Check GA4 Key Events / Conversions print("Checking GA4 events...") try: req = { "dateRanges": [{"startDate": cur_from_str, "endDate": cur_to_str}], "metrics": [{"name": "eventCount"}], "dimensions": [{"name": "eventName"}] } res = analytics.properties().runReport(property=property_id, body=req).execute() data["ga4_events"] = [] for row in res.get("rows", []): data["ga4_events"].append({ "name": row["dimensionValues"][0]["value"], "count": int(row["metricValues"][0]["value"]) }) except Exception as e: print("GA4 Events Error:", e) data["ga4_events"] = [] # 2. GA4 Daily Totals (Current & Previous) print("Fetching GA4 daily totals...") for period, start_d, end_d in [("current", cur_from_str, cur_to_str), ("previous", prev_from_str, prev_to_str)]: req = { "dateRanges": [{"startDate": start_d, "endDate": end_d}], "metrics": [ {"name": "sessions"}, {"name": "totalUsers"}, {"name": "engagedSessions"}, {"name": "conversions"} # Note: in modern GA4 api, this is 'conversions' or 'keyEvents' ], "dimensions": [{"name": "date"}] } try: res = analytics.properties().runReport(property=property_id, body=req).execute() rows_data = [] for row in res.get("rows", []): rows_data.append({ "date": row["dimensionValues"][0]["value"], "sessions": int(row["metricValues"][0]["value"]), "users": int(row["metricValues"][1]["value"]), "engaged_sessions": int(row["metricValues"][2]["value"]), "conversions": float(row["metricValues"][3]["value"]) }) data[f"ga4_daily_{period}"] = rows_data except Exception as e: # Fallback if 'conversions' field is not supported or named differently try: req["metrics"] = [ {"name": "sessions"}, {"name": "totalUsers"}, {"name": "engagedSessions"} ] res = analytics.properties().runReport(property=property_id, body=req).execute() rows_data = [] for row in res.get("rows", []): rows_data.append({ "date": row["dimensionValues"][0]["value"], "sessions": int(row["metricValues"][0]["value"]), "users": int(row["metricValues"][1]["value"]), "engaged_sessions": int(row["metricValues"][2]["value"]), "conversions": 0.0 }) data[f"ga4_daily_{period}"] = rows_data except Exception as ex: print(f"GA4 Daily {period} Error:", ex) data[f"ga4_daily_{period}"] = [] # 3. GA4 Channel Performance print("Fetching GA4 channel performance...") for period, start_d, end_d in [("current", cur_from_str, cur_to_str), ("previous", prev_from_str, prev_to_str)]: try: req = { "dateRanges": [{"startDate": start_d, "endDate": end_d}], "metrics": [ {"name": "sessions"}, {"name": "engagedSessions"}, {"name": "engagementRate"} ], "dimensions": [{"name": "sessionDefaultChannelGroup"}] } res = analytics.properties().runReport(property=property_id, body=req).execute() channels = [] for row in res.get("rows", []): channels.append({ "channel": row["dimensionValues"][0]["value"], "sessions": int(row["metricValues"][0]["value"]), "engaged_sessions": int(row["metricValues"][1]["value"]), "engagement_rate": float(row["metricValues"][2]["value"]) }) data[f"ga4_channels_{period}"] = channels except Exception as e: print(f"GA4 Channels {period} Error:", e) data[f"ga4_channels_{period}"] = [] # 4. GA4 Stacked Channel Daily (Current) print("Fetching GA4 daily channel mix...") try: req = { "dateRanges": [{"startDate": cur_from_str, "endDate": cur_to_str}], "metrics": [{"name": "sessions"}], "dimensions": [{"name": "date"}, {"name": "sessionDefaultChannelGroup"}] } res = analytics.properties().runReport(property=property_id, body=req).execute() daily_mix = [] for row in res.get("rows", []): daily_mix.append({ "date": row["dimensionValues"][0]["value"], "channel": row["dimensionValues"][1]["value"], "sessions": int(row["metricValues"][0]["value"]) }) data["ga4_daily_mix"] = daily_mix except Exception as e: print("GA4 Daily Mix Error:", e) data["ga4_daily_mix"] = [] # 5. GA4 Landing Pages print("Fetching GA4 landing pages...") try: req = { "dateRanges": [{"startDate": cur_from_str, "endDate": cur_to_str}], "metrics": [ {"name": "sessions"}, {"name": "engagedSessions"}, {"name": "engagementRate"}, {"name": "screenPageViews"} ], "dimensions": [{"name": "landingPage"}] } res = analytics.properties().runReport(property=property_id, body=req).execute() landing = [] for row in res.get("rows", []): landing.append({ "page": row["dimensionValues"][0]["value"], "sessions": int(row["metricValues"][0]["value"]), "engaged_sessions": int(row["metricValues"][1]["value"]), "engagement_rate": float(row["metricValues"][2]["value"]), "views": int(row["metricValues"][3]["value"]) }) data["ga4_landing_pages"] = landing except Exception as e: print("GA4 Landing Pages Error:", e) data["ga4_landing_pages"] = [] # 6. GSC Performance Daily (Current & Previous) print("Fetching GSC daily totals...") for period, start_d, end_d in [("current", cur_from_str, cur_to_str), ("previous", prev_from_str, prev_to_str)]: try: req = { "startDate": start_d, "endDate": end_d, "dimensions": ["date"] } res = gsc.searchanalytics().query(siteUrl=site_url, body=req).execute() rows_data = [] for row in res.get("rows", []): rows_data.append({ "date": row["keys"][0], "clicks": row["clicks"], "impressions": row["impressions"], "ctr": row["ctr"], "position": row["position"] }) data[f"gsc_daily_{period}"] = rows_data except Exception as e: print(f"GSC Daily {period} Error:", e) data[f"gsc_daily_{period}"] = [] # 7. GSC Top Queries (Current) print("Fetching GSC top queries...") try: req = { "startDate": cur_from_str, "endDate": cur_to_str, "dimensions": ["query"], "rowLimit": 150 } res = gsc.searchanalytics().query(siteUrl=site_url, body=req).execute() queries = [] for row in res.get("rows", []): queries.append({ "query": row["keys"][0], "clicks": row["clicks"], "impressions": row["impressions"], "ctr": row["ctr"], "position": row["position"] }) data["gsc_queries"] = queries except Exception as e: print("GSC Queries Error:", e) data["gsc_queries"] = [] # 8. GSC Top Pages (Current) print("Fetching GSC top pages...") try: req = { "startDate": cur_from_str, "endDate": cur_to_str, "dimensions": ["page"], "rowLimit": 150 } res = gsc.searchanalytics().query(siteUrl=site_url, body=req).execute() pages = [] for row in res.get("rows", []): pages.append({ "page": row["keys"][0], "clicks": row["clicks"], "impressions": row["impressions"], "ctr": row["ctr"], "position": row["position"] }) data["gsc_pages"] = pages except Exception as e: print("GSC Pages Error:", e) data["gsc_pages"] = [] # Save raw data os.makedirs("/opt/ai-os/products/ceo/projects/GLV/reports", exist_ok=True) out_path = "/opt/ai-os/products/ceo/projects/GLV/reports/seo_raw_data.json" with open(out_path, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) print(f"Data saved to {out_path}") if __name__ == "__main__": main()