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

You have 15 locations across 3 cities. Customer feedback varies dramatically — the downtown location gets praised for speed, the suburban one gets complaints about parking, the airport location gets dinged for prices. You pull reviews across all locations using batch endpoints, then send the aggregate to Mave for cross-location comparison. The output highlights location-specific strengths, weaknesses, and operational recommendations. Flow: Google GET /accounts/{id}/locations → Per-location GET /locations/{id}/reviews → Aggregate → Mavera POST /mave/chat → Cross-location analysis

Architecture

Code

import os, requests, time
from collections import defaultdict

GOOG = os.environ["GOOGLE_ACCESS_TOKEN"]
ACCT = os.environ["GOOGLE_ACCOUNT_ID"]
MV = os.environ["MAVERA_API_KEY"]
GB_BASE = "https://mybusiness.googleapis.com/v4"
MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
GB_H = {"Authorization": f"Bearer {GOOG}"}

# 1. List all locations
locations = requests.get(f"{GB_BASE}/{ACCT}/locations",
    headers=GB_H,
    params={"pageSize": 100}).json().get("locations", [])

print(f"Found {len(locations)} locations")

# 2. Pull reviews for each location
location_data = []
for loc in locations:
    loc_id = loc.get("name", "")
    loc_name = loc.get("locationName", loc.get("title", "Unknown"))
    address = loc.get("address", {})
    city = address.get("locality", "Unknown")
    state = address.get("administrativeArea", "")

    reviews = []
    page_token = None
    while len(reviews) < 100:
        params = {"pageSize": 50}
        if page_token:
            params["pageToken"] = page_token
        r = requests.get(f"{GB_BASE}/{loc_id}/reviews",
            headers=GB_H, params=params)
        if r.status_code == 429:
            time.sleep(2)
            continue
        if r.status_code != 200:
            break
        data = r.json()
        reviews.extend(data.get("reviews", []))
        page_token = data.get("nextPageToken")
        if not page_token:
            break
        time.sleep(0.3)

    ratings = [rev.get("starRating", "FIVE") for rev in reviews]
    star_map = {"ONE": 1, "TWO": 2, "THREE": 3, "FOUR": 4, "FIVE": 5}
    numeric_ratings = [star_map.get(r, 3) for r in ratings]
    avg_rating = sum(numeric_ratings) / len(numeric_ratings) if numeric_ratings else 0

    review_texts = []
    for rev in reviews:
        comment = rev.get("comment", "")
        if comment:
            stars = star_map.get(rev.get("starRating", "FIVE"), 5)
            review_texts.append(f"[{stars}★] {comment[:200]}")

    location_data.append({
        "name": loc_name,
        "city": city,
        "state": state,
        "review_count": len(reviews),
        "avg_rating": round(avg_rating, 1),
        "reviews": review_texts,
    })
    time.sleep(0.5)

# 3. Mave cross-location analysis
loc_block = "\n\n".join(
    f"## {ld['name']} ({ld['city']}, {ld['state']})\n"
    f"Reviews: {ld['review_count']} | Avg: {ld['avg_rating']}/5\n"
    f"Sample reviews:\n" + "\n".join(ld["reviews"][:5])
    for ld in location_data
)

analysis = requests.post("https://app.mavera.io/api/v1/mave/chat",
    headers=MV_H,
    json={"message": f"""Compare customer feedback across these {len(location_data)} business locations.

{loc_block}

Produce:
1. Location ranking (best to worst by customer satisfaction)
2. Per-location strengths (what each does well)
3. Per-location weaknesses (what each needs to fix)
4. Cross-location patterns (issues affecting multiple locations)
5. Location-specific operational recommendations
6. Best practices from top-rated locations to apply elsewhere"""}).json()

print("=== Multi-Location Review Intelligence ===")
print(analysis.get("content", "")[:2000])

Example Output

=== Multi-Location Review Intelligence ===

## Location Ranking
1. Downtown (4.6/5, 234 reviews) — Top performer
2. Midtown (4.3/5, 178 reviews) — Strong with minor issues
3. Airport (3.8/5, 312 reviews) — High volume, lower satisfaction
4. Suburbs (3.5/5, 89 reviews) — Needs attention

## Per-Location Strengths
- **Downtown**: Speed of service (mentioned 45x), friendly staff (38x)
- **Midtown**: Product quality (32x), ambiance (21x)
- **Airport**: Convenience/hours (28x), location (25x)
- **Suburbs**: Parking (22x), family-friendly (15x)

## Per-Location Weaknesses
- **Airport**: Price complaints (67x — "airport markup"), wait times (34x)
- **Suburbs**: Slow service (18x), limited menu (12x)
- **Downtown**: Parking (14x), crowding (11x)

## Cross-Location Pattern
Wait time complaints appear at 3/4 locations — systemic staffing issue.
Recommendation: Implement queue management across all locations.

## Best Practice Transfer
Downtown's staffing model (shift overlap during peak) should be replicated.
Airport needs differentiated pricing communication ("value menu" framing).

Error Handling

Google uses string ratings (ONE, TWO, etc.), not numbers. The code maps these to 1-5 integers.
Google uses opaque nextPageToken cursors. Never cache or reuse tokens across sessions.
Access tokens expire in 1 hour. Use a refresh token flow or service account for automated jobs.