## Parallel Data Fetch Pattern
When fetching from multiple sources, issue all requests in a SINGLE message
for parallel execution:
┌─────────────────────────────────────────────────────────────────┐
│ MESSAGE 1: Parallel Data Requests │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [MCP Call 1]: google-analytics.get_report(...) │
│ [MCP Call 2]: google-search-console.search_analytics(...) │
│ │
│ → All execute simultaneously │
│ → Results return when all complete │
│ → ~2x faster than sequential │
│ │
└─────────────────────────────────────────────────────────────────┘
Sequential (When Needed)
Some operations require sequential execution:
## Sequential Pattern (Dependencies)
When one request depends on another's result:
┌─────────────────────────────────────────────────────────────────┐
│ MESSAGE 1: Get list of pages │
│ → Returns: ["/page1", "/page2", "/page3"] │
├─────────────────────────────────────────────────────────────────┤
│ MESSAGE 2: Get details for each page │
│ → Uses page list from Message 1 │
│ → Can parallelize within this message │
└─────────────────────────────────────────────────────────────────┘
# Cache structure
SESSION_PATH="/tmp/seo-performance-20251227-143000-example"
CACHE_DIR="${SESSION_PATH}/cache"
CACHE_TTL=3600 # 1 hour in secondsmkdir -p "$CACHE_DIR"# Cache key generationcache_key() {
echo"$1" | md5sum | cut -d' ' -f1
}
# Check cacheget_cached() {
local key=$(cache_key "$1")
local cache_file="${CACHE_DIR}/${key}.json"if [ -f "$cache_file" ]; thenlocal age=$(($(date +%s) - $(stat -f%m "$cache_file" 2>/dev/null || stat -c%Y "$cache_file")))
if [ $age -lt $CACHE_TTL ]; thencat"$cache_file"return 0
fifireturn 1
}
# Save to cachesave_cache() {
local key=$(cache_key "$1")
local cache_file="${CACHE_DIR}/${key}.json"cat > "$cache_file"
}
# Usage
CACHE_KEY="ga4_${URL}_${DATE_RANGE}"if ! RESULT=$(get_cached "$CACHE_KEY"); then
RESULT=$(fetch_from_api)
echo"$RESULT" | save_cache "$CACHE_KEY"fi
Date Range Standardization
Common Date Ranges
# Standard date range calculations
TODAY=$(date +%Y-%m-%d)
case"$RANGE"in"7d")
START_DATE=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d "7 days ago" +%Y-%m-%d)
;;
"30d")
START_DATE=$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d "30 days ago" +%Y-%m-%d)
;;
"90d")
START_DATE=$(date -v-90d +%Y-%m-%d 2>/dev/null || date -d "90 days ago" +%Y-%m-%d)
;;
"mtd")
START_DATE=$(date +%Y-%m-01)
;;
"ytd")
START_DATE=$(date +%Y-01-01)
;;
esac
END_DATE="$TODAY"
API-Specific Formats
API
Format
Example
GA4
Relative or ISO
"30daysAgo", "2025-12-01"
GSC
ISO 8601
"2025-12-01"
Graceful Degradation
Data Source Fallback
## Fallback Strategy
When a data source is unavailable:
┌─────────────────────────────────────────────────────────────────┐
│ PRIMARY SOURCE │ FALLBACK │ LAST RESORT │
├──────────────────────┼─────────────────────┼────────────────────┤
│ GA4 traffic data │ GSC clicks │ Estimate from GSC │
│ GSC search perf │ Manual SERP check │ WebSearch SERP │
│ CWV (CrUX) │ PageSpeed API │ Lighthouse CLI │
└──────────────────────┴─────────────────────┴────────────────────┘
Partial Data Output
## Analysis Report (Partial Data)### Data Availability
| Source | Status | Impact |
|--------|--------|--------|
| GA4 | NOT CONFIGURED | Missing engagement metrics |
| GSC | AVAILABLE | Full search data |
### Analysis Notes
This analysis is based on limited data sources:
- Search performance metrics are complete (GSC)
- Engagement metrics unavailable (no GA4)
**Recommendation**: Configure GA4 for complete analysis.
Run `/setup-analytics` to add Google Analytics.
## Data Fetch Error**Source**: Google Analytics 4
**Error**: 403 Forbidden
**Message**: "User does not have sufficient permissions for this property"
### Troubleshooting Steps1. Verify Service Account email in GA4 Admin
2. Ensure "Viewer" role is granted
3. Check Analytics Data API is enabled
4. Wait 5 minutes for permission propagation
### Workaround
Proceeding with available data sources (GSC).
GA4 engagement metrics will not be included in this analysis.