- Added scroll depth tracking (25%, 50%, 75%) - Track form interactions and outbound clicks - Added engagement rate, avg session duration, page views - Updated daily report with comprehensive engagement metrics - Created ga4-list-events.py to discover tracked events - All metrics now flow to morning brief
162 lines
6.3 KiB
Python
162 lines
6.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Google Analytics 4 - Direct JWT Authentication (No gcloud required)
|
|
Enhanced to pull: sessions, users, engagement, scroll depth, form interactions
|
|
"""
|
|
import json
|
|
from datetime import datetime, timedelta
|
|
from pathlib import Path
|
|
from google.analytics.data import BetaAnalyticsDataClient
|
|
from google.analytics.data_v1beta.types import RunReportRequest, DateRange, Metric, Dimension, Filter, FilterExpression
|
|
|
|
CONFIG_DIR = Path(__file__).parent.parent / "config"
|
|
GA_CREDENTIALS = CONFIG_DIR / "ga-credentials.json"
|
|
GA_PROPERTY_ID = "526394825"
|
|
|
|
def load_credentials():
|
|
"""Load service account credentials"""
|
|
with open(GA_CREDENTIALS) as f:
|
|
return json.load(f)
|
|
|
|
def get_engagement_data():
|
|
"""Get comprehensive engagement metrics"""
|
|
try:
|
|
client = BetaAnalyticsDataClient.from_service_account_json(str(GA_CREDENTIALS))
|
|
|
|
# Main traffic report
|
|
request = RunReportRequest(
|
|
property=f"properties/{GA_PROPERTY_ID}",
|
|
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"),
|
|
Metric(name="engagementRate"),
|
|
Metric(name="screenPageViews"),
|
|
]
|
|
)
|
|
|
|
response = client.run_report(request)
|
|
|
|
result = {
|
|
"success": True,
|
|
"timestamp": datetime.now().isoformat()
|
|
}
|
|
|
|
for row in response.rows:
|
|
result['sessions'] = int(row.metric_values[0].value)
|
|
result['activeUsers'] = int(row.metric_values[1].value)
|
|
result['newUsers'] = int(row.metric_values[2].value)
|
|
result['bounceRate'] = float(row.metric_values[3].value)
|
|
result['averageSessionDuration'] = float(row.metric_values[4].value)
|
|
result['engagementRate'] = float(row.metric_values[5].value)
|
|
result['screenPageViews'] = int(row.metric_values[6].value)
|
|
|
|
# Get scroll depth events
|
|
scroll_request = RunReportRequest(
|
|
property=f"properties/{GA_PROPERTY_ID}",
|
|
dimensions=[Dimension(name="eventName")],
|
|
metrics=[Metric(name="eventCount")],
|
|
date_ranges=[DateRange(start_date="1daysAgo", end_date="today")],
|
|
dimension_filter=FilterExpression(
|
|
filter=Filter(
|
|
field_name="eventName",
|
|
string_filter=Filter.StringFilter(
|
|
match_type=Filter.StringFilter.MatchType.BEGINS_WITH,
|
|
value="scroll"
|
|
)
|
|
)
|
|
),
|
|
limit=10
|
|
)
|
|
|
|
scroll_response = client.run_report(scroll_request)
|
|
scroll_data = {}
|
|
for row in scroll_response.rows:
|
|
event_name = row.dimension_values[0].value
|
|
count = int(row.metric_values[0].value)
|
|
scroll_data[event_name] = count
|
|
|
|
result['scroll_25'] = scroll_data.get('scroll_25', 0)
|
|
result['scroll_50'] = scroll_data.get('scroll_50', 0)
|
|
result['scroll_75'] = scroll_data.get('scroll_75', 0)
|
|
result['scroll_total'] = sum(scroll_data.values())
|
|
|
|
# Get form interactions
|
|
form_request = RunReportRequest(
|
|
property=f"properties/{GA_PROPERTY_ID}",
|
|
metrics=[Metric(name="eventCount")],
|
|
date_ranges=[DateRange(start_date="1daysAgo", end_date="today")],
|
|
dimension_filter=FilterExpression(
|
|
filter=Filter(
|
|
field_name="eventName",
|
|
string_filter=Filter.StringFilter(
|
|
match_type=Filter.StringFilter.MatchType.EXACT,
|
|
value="form_start"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
form_response = client.run_report(form_request)
|
|
form_count = 0
|
|
for row in form_response.rows:
|
|
form_count += int(row.metric_values[0].value)
|
|
|
|
result['form_interactions'] = form_count
|
|
|
|
# Get click events (outbound clicks)
|
|
click_request = RunReportRequest(
|
|
property=f"properties/{GA_PROPERTY_ID}",
|
|
metrics=[Metric(name="eventCount")],
|
|
date_ranges=[DateRange(start_date="1daysAgo", end_date="today")],
|
|
dimension_filter=FilterExpression(
|
|
filter=Filter(
|
|
field_name="eventName",
|
|
string_filter=Filter.StringFilter(
|
|
match_type=Filter.StringFilter.MatchType.EXACT,
|
|
value="click"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
click_response = client.run_report(click_request)
|
|
click_count = 0
|
|
for row in click_response.rows:
|
|
click_count += int(row.metric_values[0].value)
|
|
|
|
result['outbound_clicks'] = click_count
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
return {"success": False, "error": str(e)}
|
|
|
|
if __name__ == "__main__":
|
|
print("🚀 Fetching GA4 Analytics Data...\n")
|
|
|
|
result = get_engagement_data()
|
|
|
|
if result.get('success'):
|
|
print("📊 Traffic (Last 24h):")
|
|
print(f" ✅ Sessions: {result.get('sessions', 0):,}")
|
|
print(f" ✅ Active Users: {result.get('activeUsers', 0):,}")
|
|
print(f" ✅ New Users: {result.get('newUsers', 0):,}")
|
|
print(f" ✅ Engagement Rate: {result.get('engagementRate', 0):.1%}")
|
|
print(f" ✅ Bounce Rate: {result.get('bounceRate', 0):.1%}")
|
|
print(f" ✅ Avg Session: {result.get('averageSessionDuration', 0):.1f}s")
|
|
print(f" ✅ Page Views: {result.get('screenPageViews', 0):,}")
|
|
|
|
print("\n🎯 Engagement Events:")
|
|
print(f" • Scroll Depth 25%: {result.get('scroll_25', 0)}")
|
|
print(f" • Scroll Depth 50%: {result.get('scroll_50', 0)}")
|
|
print(f" • Scroll Depth 75%: {result.get('scroll_75', 0)}")
|
|
print(f" • Form Interactions: {result.get('form_interactions', 0)}")
|
|
print(f" • Outbound Clicks: {result.get('outbound_clicks', 0)}")
|
|
|
|
else:
|
|
print(f"❌ Error: {result.get('error')}")
|