OPS ► MARKETING COMMAND CENTER
Runtime Context
Before executing, load available context:
-
Preferences: Read
${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.jsontimezone— display all timestamps correctlyklaviyo_private_key,meta_ads_token,meta_ad_account_id,ga4_property_id,google_search_console_site— check userConfig keys before env varsgoogle_ads_developer_token,google_ads_client_id,google_ads_client_secret,google_ads_refresh_token,google_ads_customer_id,google_ads_login_customer_id— Google Ads credentials
-
Daemon health: Read
${CLAUDE_PLUGIN_DATA_DIR}/daemon-health.json- If
action_neededis not null → surface it before running any channel queries
- If
-
Secrets: Resolve API keys via userConfig → env vars → Doppler MCP (
mcp__doppler__*) → Doppler CLI fallback (see Credential Resolution section below)
CLI/API Reference
Klaviyo REST API
| Endpoint | Method | Description |
|---|---|---|
https://a.klaviyo.com/api/lists/?fields[list]=name,id,profile_count | GET | All lists + subscriber counts |
https://a.klaviyo.com/api/campaigns/?filter=equals(messages.channel,'email')&sort=-created_at | GET | Recent campaigns |
https://a.klaviyo.com/api/flows/?filter=equals(status,'live') | GET | Active flows |
https://a.klaviyo.com/api/metrics/ | GET | Available metrics |
Auth header: Authorization: Klaviyo-API-Key ${KLAVIYO_KEY} | Revision header: revision: 2024-10-15
Meta Graph API
| Endpoint | Method | Description |
|---|---|---|
https://graph.facebook.com/v18.0/${META_ACCOUNT}/insights?fields=spend,...&date_preset=last_7d | GET | Account-level ad spend |
https://graph.facebook.com/v18.0/${META_ACCOUNT}/campaigns?fields=name,status,insights{...} | GET | Campaign breakdown |
https://graph.facebook.com/v18.0/me/accounts?fields=instagram_business_account | GET | Linked Instagram account |
Auth header: Authorization: Bearer ${META_TOKEN}
Google Analytics 4 (Data API)
| Endpoint | Method | Description |
|---|---|---|
https://analyticsdata.googleapis.com/v1beta/properties/${GA4_PROPERTY}:runReport | POST | Run custom report |
Auth: gcloud ADC — GA4_TOKEN=$(gcloud auth application-default print-access-token)
Google Search Console
| Endpoint | Method | Description |
|---|---|---|
https://searchconsole.googleapis.com/webmasters/v3/sites/${GSC_SITE_ENCODED}/searchAnalytics/query | POST | Search performance data |
Auth: Same gcloud ADC token as GA4
Agent Teams support
If CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 is set, use Agent Teams when gathering channel data in parallel. This enables:
- Agents share context and can coordinate mid-flight
- You can steer priorities in real-time
- Agents report progress as they complete
Team setup (only when flag is enabled):
TeamCreate("marketing-team")
Agent(team_name="marketing-team", name="email-metrics", prompt="Pull Klaviyo subscriber counts, campaign stats, and flow metrics")
Agent(team_name="marketing-team", name="ads-metrics", prompt="Pull Meta Ads spend, ROAS, and campaign breakdown")
Agent(team_name="marketing-team", name="analytics-metrics", prompt="Pull GA4 sessions, conversions, and traffic sources")
Agent(team_name="marketing-team", name="seo-metrics", prompt="Pull Search Console clicks, impressions, and top queries")
If the flag is NOT set, use standard fire-and-forget subagents.
Credential Resolution
Resolve credentials in this order for each service:
Klaviyo
KLAVIYO_KEY="${KLAVIYO_PRIVATE_KEY:-$(claude plugin config get klaviyo_private_key 2>/dev/null)}"
if [ -z "$KLAVIYO_KEY" ]; then
KLAVIYO_KEY="$(doppler secrets get KLAVIYO_PRIVATE_KEY --plain 2>/dev/null)"
fi
Meta Ads
META_TOKEN="${META_ADS_TOKEN:-$(claude plugin config get meta_ads_token 2>/dev/null)}"
META_ACCOUNT="${META_AD_ACCOUNT_ID:-$(claude plugin config get meta_ad_account_id 2>/dev/null)}"
if [ -z "$META_TOKEN" ]; then
META_TOKEN="$(doppler secrets get META_ADS_TOKEN --plain 2>/dev/null)"
fi
GA4
GA4_PROPERTY="${GA4_PROPERTY_ID:-$(claude plugin config get ga4_property_id 2>/dev/null)}"
# GA4 uses gcloud application default credentials — check if configured:
gcloud auth application-default print-access-token 2>/dev/null
Google Search Console
GSC_SITE="${GOOGLE_SEARCH_CONSOLE_SITE:-$(claude plugin config get google_search_console_site 2>/dev/null)}"
# Uses same gcloud ADC as GA4
Google Ads
GADS_API_VERSION="v23"
GADS_DEV_TOKEN="${GOOGLE_ADS_DEVELOPER_TOKEN:-$(claude plugin config get google_ads_developer_token 2>/dev/null)}"
GADS_CLIENT_ID="${GOOGLE_ADS_CLIENT_ID:-$(claude plugin config get google_ads_client_id 2>/dev/null)}"
GADS_CLIENT_SECRET="${GOOGLE_ADS_CLIENT_SECRET:-$(claude plugin config get google_ads_client_secret 2>/dev/null)}"
GADS_REFRESH_TOKEN="${GOOGLE_ADS_REFRESH_TOKEN:-$(claude plugin config get google_ads_refresh_token 2>/dev/null)}"
GADS_CUSTOMER_ID="${GOOGLE_ADS_CUSTOMER_ID:-$(claude plugin config get google_ads_customer_id 2>/dev/null)}"
GADS_LOGIN_CUSTOMER_ID="${GOOGLE_ADS_LOGIN_CUSTOMER_ID:-$(claude plugin config get google_ads_login_customer_id 2>/dev/null)}"
# Doppler fallback
if [ -z "$GADS_REFRESH_TOKEN" ]; then
GADS_REFRESH_TOKEN="$(doppler secrets get GOOGLE_ADS_REFRESH_TOKEN --plain 2>/dev/null)"
fi
if [ -z "$GADS_DEV_TOKEN" ]; then
GADS_DEV_TOKEN="$(doppler secrets get GOOGLE_ADS_DEVELOPER_TOKEN --plain 2>/dev/null)"
fi
# Strip dashes from customer ID (API requires no dashes)
GADS_CUSTOMER_ID="${GADS_CUSTOMER_ID//-/}"
# Refresh access token (expires in ~1 hour — always refresh before API calls)
GADS_ACCESS_TOKEN=$(curl -s -X POST https://oauth2.googleapis.com/token \
--data "client_id=${GADS_CLIENT_ID}" \
--data "client_secret=${GADS_CLIENT_SECRET}" \
--data "refresh_token=${GADS_REFRESH_TOKEN}" \
--data "grant_type=refresh_token" | jq -r '.access_token')
# Common headers for all Google Ads API calls
GADS_HEADERS=(-H "Content-Type: application/json" -H "Authorization: Bearer ${GADS_ACCESS_TOKEN}" -H "developer-token: ${GADS_DEV_TOKEN}")
if [ -n "$GADS_LOGIN_CUSTOMER_ID" ]; then
GADS_HEADERS+=(-H "login-customer-id: ${GADS_LOGIN_CUSTOMER_ID}")
fi
Sub-command Routing
Route $ARGUMENTS to the correct section below:
| Input | Action |
|---|---|
| (empty), dashboard | Run full marketing dashboard |
| email, klaviyo | Klaviyo email metrics |
| ads, meta | Meta Ads performance (read-only overview) |
| meta-manage, meta create-campaign, meta target, meta creative, meta rules, meta audiences, meta advantage | Meta Ads campaign management (see ## meta-manage section) |
| google-ads, gads | Google Ads dashboard + campaign management (see ## google-ads section) |
| analytics, ga4 | GA4 sessions + conversions |
| ga4 realtime, ga4 funnel, ga4 cohort, ga4 audience, ga4 pivot | GA4 advanced analytics (see ## ga4-advanced section) |
| seo, gsc | Search Console metrics |
| social | Social media aggregator |
| instagram, instagram post, instagram reel, instagram story, instagram insights, instagram demographics | Instagram publishing + insights (see ## instagram section) |
| campaigns | Cross-channel campaign overview (all platforms) |
| optimize | Cross-platform ad optimization agent |
| attribution | Unified attribution table (Meta + Google + Klaviyo + GA4) |
| setup | Configure API keys |
email / klaviyo
Pull Klaviyo metrics for last 30 days.
Subscriber count
curl -s "https://a.klaviyo.com/api/lists/?fields[list]=name,id,profile_count" \
-H "Authorization: Klaviyo-API-Key ${KLAVIYO_KEY}" \
-H "revision: 2024-10-15" | jq '.data[] | {name: .attributes.name, id: .id, count: .attributes.profile_count}'
Recent campaigns (last 10)
curl -s "https://a.klaviyo.com/