Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mavera.io/llms.txt

Use this file to discover all available pages before exploring further.

Scenario

Your top landing pages are underperforming — high traffic but poor engagement or high bounce rates. You pull the worst-performing high-traffic pages from GA4, then use Mavera’s Generate endpoint to rewrite the copy for a specific audience segment, applying your brand voice. The result is refreshed landing page copy informed by actual performance data.

Architecture

Code

import os, requests
from google.analytics.data_v1beta import BetaAnalyticsDataClient
from google.analytics.data_v1beta.types import (
    RunReportRequest, Dimension, Metric, DateRange, OrderBy, FilterExpression,
    Filter,
)

PROPERTY_ID = os.environ["GA4_PROPERTY_ID"]
MV = os.environ["MAVERA_API_KEY"]
MB = "https://app.mavera.io/api/v1"
MH = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}

client = BetaAnalyticsDataClient()

report = client.run_report(RunReportRequest(
    property=f"properties/{PROPERTY_ID}",
    dimensions=[Dimension(name="landingPage")],
    metrics=[
        Metric(name="totalUsers"),
        Metric(name="bounceRate"),
        Metric(name="engagementRate"),
        Metric(name="averageSessionDuration"),
        Metric(name="conversions"),
        Metric(name="screenPageViews"),
    ],
    date_ranges=[DateRange(start_date="30daysAgo", end_date="today")],
    dimension_filter=FilterExpression(filter=Filter(
        field_name="landingPage",
        string_filter=Filter.StringFilter(
            match_type=Filter.StringFilter.MatchType.BEGINS_WITH,
            value="/",
        ),
    )),
    order_bys=[OrderBy(metric=OrderBy.MetricOrderBy(metric_name="totalUsers"), desc=True)],
    limit=50,
))

pages = []
for row in report.rows:
    path = row.dimension_values[0].value
    users = int(row.metric_values[0].value)
    bounce = float(row.metric_values[1].value)
    engagement = float(row.metric_values[2].value)
    duration = float(row.metric_values[3].value)
    conversions = int(row.metric_values[4].value)
    views = int(row.metric_values[5].value)

    if users < 100:
        continue

    pages.append({
        "path": path, "users": users, "bounce": bounce,
        "engagement": engagement, "duration": duration,
        "conversions": conversions, "views": views,
        "conv_rate": conversions / max(users, 1),
    })

needs_refresh = [p for p in pages if p["bounce"] > 0.6 or p["engagement"] < 0.4]
needs_refresh.sort(key=lambda p: p["users"], reverse=True)

BRAND_VOICE_ID = os.environ.get("BRAND_VOICE_ID", "")
AUDIENCE = "B2B marketing directors at mid-market SaaS companies (200–2000 employees)"

print(f"Pages needing refresh: {len(needs_refresh)} of {len(pages)} total\n")

for page in needs_refresh[:5]:
    prompt = (
        f"Rewrite the landing page copy for this URL path: {page['path']}\n\n"
        f"CURRENT PERFORMANCE (last 30 days):\n"
        f"- Users: {page['users']}\n"
        f"- Bounce rate: {page['bounce']:.0%}\n"
        f"- Engagement rate: {page['engagement']:.0%}\n"
        f"- Avg session duration: {page['duration']:.0f}s\n"
        f"- Conversion rate: {page['conv_rate']:.2%}\n\n"
        f"TARGET AUDIENCE: {AUDIENCE}\n\n"
        f"Generate:\n"
        f"1. New H1 headline (max 10 words)\n"
        f"2. Sub-headline (max 20 words)\n"
        f"3. 3 benefit bullet points (max 15 words each)\n"
        f"4. CTA button text (max 5 words)\n"
        f"5. Social proof line (max 15 words)\n\n"
        f"The current copy has a {page['bounce']:.0%} bounce rate — the rewrite must hook visitors in 3 seconds."
    )

    payload = {"prompt": prompt}
    if BRAND_VOICE_ID:
        payload["brand_voice_id"] = BRAND_VOICE_ID

    gen = requests.post(f"{MB}/generations", headers=MH, json=payload).json()

    print(f"{'='*50}")
    print(f"Page: {page['path']}")
    print(f"Users: {page['users']} | Bounce: {page['bounce']:.0%} | Engagement: {page['engagement']:.0%}")
    print(f"{'='*50}")
    print(gen.get("output", gen.get("content", ""))[:600])
    print()

Example Output

Pages needing refresh: 8 of 34

==================================================
Page: /features/analytics
Users: 2,340 | Bounce: 72% | Engagement: 31%
==================================================
1. H1: Stop Guessing. Start Knowing Your Audience.
2. Sub: Real-time persona intelligence that turns GA4 data into
   actionable content strategy.
3. Benefits:
   - Build personas from your actual converting demographics
   - Test messaging with synthetic focus groups before launch
   - Generate brand-aligned content in minutes, not weeks
4. CTA: Start Free — No Credit Card
5. Social proof: Trusted by 2,000+ marketing teams at companies like
   Notion, Figma, and Ramp.

Error Handling

GA4 reports landingPage as path only (e.g. /pricing), not full URLs. If you need to pass actual page content to Generate, fetch the page HTML separately or maintain a content map.
If BRAND_VOICE_ID is invalid, the Generate call returns 404. Omit the field to use Mavera’s default voice, or create a voice first via POST /api/v1/brand-voices.
GA4’s bounce rate = 100% minus engagement rate. A “bounced” session has no engagement events, lasts under 10 seconds, and has no conversions. This differs from Universal Analytics.

What’s Next

GA4 Integration

Back to GA4 integration overview

Conversion Path → Focus Group Validation

Validate funnel drop-offs with focus groups

Real-Time Audience → Trending Response

Diagnose traffic spikes in real time

Generate API

Full reference for POST /api/v1/generations