# Xylo > Xylo is the connector that lets any AI agent run your Meta, Google, and TikTok ad accounts in plain English. Connect your accounts once, point your AI app at Xylo, then just talk to it. Hand your ad accounts to an AI agent. - [Documentation](https://xylomcp.com/docs) - [MCP Tool Reference (300+ ad operations)](https://xylomcp.com/mcp-tools.md) - [Xylo Claude Skill (downloadable)](https://xylomcp.com/xylo-skill.md) - [Pricing](https://xylomcp.com/#pricing) - [Sign Up Free](https://xylomcp.com/auth/signup) --- # Xylo Agent Playbook ## How AI Agents Should Use Xylo to Manage Ads This document is meant to be loaded into an AI agent's context when it has access to Xylo. It teaches the agent HOW to think about paid advertising across Meta (Facebook and Instagram), Google Ads, and TikTok Ads, not just which tools to call, but what to look at, what matters, and how to make smart decisions on the user's behalf. ### What Xylo is Xylo is an MCP server (a connector). The user connects their ad accounts once via OAuth, then points an MCP-compatible app (Claude, ChatGPT, Cursor, Claude Code, Codex, and others) at the Xylo endpoint `https://xylomcp.com/api/mcp`. From there, the agent acts on the account through 300+ read and write ad operations that span Meta, Google, and TikTok, plus AI, creative-analysis, and cross-platform reporting, delivered as 25 tools that load instantly in any AI client. The operations cover essentially every Ads Manager surface. Platform choice is the `channel` parameter on each call. Ad account tokens are encrypted (AES-256-GCM) and the agent never sees the user's credentials. New campaigns are created PAUSED so nothing spends until the user approves. High-risk writes (deletes, budget or bid raises, large bulk activations) return a dry-run preview with a `confirm_token` and execute only when the same call is re-sent with the token. ### Tool-and-intent model (lead with this) Xylo exposes 25 tools: 18 resource-named dispatchers (`accounts`, `query`, `insights`, `plan`, `creative`, `competitors`, `warehouse`, `knowledge`, `create`, `update`, `status`, `delete`, `duplicate`, `media`, `publish`, `tracking`, `automation`, `connect`), two discovery helpers (`describe`, `search_tools`), four named AI tools (`audit_campaign`, `optimize_budget`, `generate_report`, `morpheus_audit`), and `send_feedback`. Every dispatcher call has the same shape: pick a route with top-level discriminators (`channel` / `resource` / `action` / `mode` / `lens` / `topic`), and nest ALL of the route's arguments under a single `params` object, never at the top level. For example: - List Meta campaigns: `query({ channel: "meta", resource: "campaign", mode: "list", params: { ... } })` - Campaign performance: `insights({ channel: "google", lens: "campaign", params: { ... } })` - One normalized report across all three platforms: `insights({ channel: "cross", lens: "cross_platform", params: { ... } })` - Create a TikTok ad group: `create({ channel: "tiktok", resource: "ad_group", mode: "single", params: { ... } })` - Pause a Meta ad set: `status({ channel: "meta", resource: "adset", params: { ... } })` - Analyze a creative: `creative({ action: "analyze", channel: "meta", params: { ... } })` Think in terms of intent and the route that satisfies it, not raw HTTP. Unfamiliar route? `describe({ tool, ...discriminators })` returns its exact input schema (batch several with `routes: [...]`); `search_tools({ query })` finds routes by intent. Wrong guesses are cheap: errors self-correct by returning the route's compact schema plus a valid example. When this playbook shows a REST snippet (for example `GET /v1/campaigns`), treat it as the secondary developer equivalent of a tool call. The same data and actions are available through the MCP tools, and through agents you should prefer the tools. The REST API exists for developers who integrate directly (base URL `https://api.xylomcp.com`, auth header `x-api-key: xy_sk_...`); it is not the primary path for an agent. ### Efficient, precise reads (built for agents) Xylo's read tools are designed to keep your context lean — pull exactly what a question needs instead of loading whole objects: - **`fields` allowlist.** Every Meta list/get route (campaigns, ad sets, ads) accepts a `fields` array in `params` — ask for only the fields you need and get just those (plus `id`). "What are my ad set budgets?" → `query({ channel: "meta", resource: "adset", mode: "list", params: { campaign_id, fields: ["daily_budget"] } })` returns `[{ id, daily_budget }]` and nothing else. Ad-set `targeting` (which can carry thousands of ZIP codes) is opt-in: omitted by default, included only when you list it in `fields`. - **`delivery_status` for true run-state.** Campaigns, ad sets, and ads return a derived `delivery_status` (ACTIVE / PAUSED / COMPLETED / SCHEDULED / …). Read it — not raw `status` — to know what is actually live: Meta leaves a finished entity at status=ACTIVE, so a completed campaign reads `delivery_status: COMPLETED`. Google campaigns carry it too (Google's `primary_status`): `status: ENABLED` with a past end date reads `delivery_status: ENDED`. ### Platform note Most of the strategy below (account discovery, daily monitoring, scaling, killing underperformers, audience structure, metrics, safety) is platform-agnostic and applies to Meta, Google, and TikTok. Where a platform differs in a meaningful way, there is a short per-platform note. TikTok coverage in Xylo is for ADS management only: campaigns, ad groups, ads, insights, audiences, GMV Max, and Smart+. Xylo does not post organic content. --- ## 1. First connection: understanding an account When a user first connects an ad account through Xylo, the agent should run a discovery sequence to build context. This is the agent's onboarding: it needs to understand the account before it can be useful. Run the equivalent discovery on each connected platform. ### Step 1: Account overview List connected accounts and read account details (tool: `accounts({ channel: "meta" | "google" | "tiktok", action: "list" })`; REST: `GET /v1/accounts`, `GET /v1/google/accounts`, `GET /v1/tiktok/accounts`). Note each account's currency, timezone, and (on Meta) spend cap. These fundamentals affect everything downstream. An account in EUR on a Berlin timezone has different reporting windows than one in USD on Eastern time. ### Step 2: Campaign audit List campaigns by status (tool: `query({ channel, resource: "campaign", mode: "list" })`). Build a mental model of account structure: - How many active campaigns are running on each platform? - What objectives are they using? (Meta: OUTCOME_SALES, OUTCOME_LEADS, OUTCOME_AWARENESS, etc. Google: Search, Performance Max, Display, Video. TikTok: traffic, conversions, product sales / GMV Max, Smart+.) - How are budgets distributed? Is spend concentrated in one campaign or spread across many? - Are there paused campaigns that hold useful historical data? ### Step 3: Performance baseline Pull insights at account and campaign level for the last 30 days (tool: `insights` with `lens: "account"` or `lens: "campaign"` per channel; cross-platform: `insights({ channel: "cross", lens: "cross_platform" })`). Establish baselines: - Overall monthly spend per platform and combined. - Average CPC, CPM, CTR. - Average cost per conversion and ROAS. - Which campaigns are above or below the account average. The `cross_platform` lens returns one normalized report across Meta, Google, and TikTok with per-platform totals and a grand total. Use it when the user asks "how are we doing overall." ### Step 4: Audience and creative landscape List audiences and the ad sets / ad groups under each active campaign (tool: `query` with `mode: "list"` and `resource: "audience"` / `"adset"` / `"ad_group"` / `"saved_audience"` per channel). Understand who is being targeted: - What custom audiences exist? What lookalikes are in use? - What age / gender / location targeting is most common? - Broad targeting or detailed interest / keyword targeting? - Google specifics: which keywords, match types, and negative keyword lists are in place. ### Step 5: Identities, pages, and connected profiles Identify the brand profiles ads run from. On Meta, find the Facebook Page and Instagram account (tool: `query({ channel: "meta", resource: "page" | "instagram_account", mode: "list" })`). On TikTok, list identities (tool: `accounts({ channel: "tiktok", action: "identities" })`). These are needed for creating ads and for organic context. ### Step 6: Conversion tracking, lead forms, and catalogs Check the account's measurement and commerce setup: - Meta: pixels / datasets, lead forms, and product catalogs (tool: `query`, `mode: "list"`, `resource: "pixel"` / `"lead_form"` / `"catalog"`). - Google: conversion actions (tool: `query({ channel: "google", resource: "conversion_action", mode: "list" })`). - TikTok: pixels and catalogs (tool: `query`, `mode: "list"`, `resource: "pixel"` / `"catalog"`). These indicate what kind of campaigns the user runs. Lead forms present means lead gen (monitor lead volume and follow-up timing). Product catalogs present means e-commerce with dynamic / shopping ads (understand catalog size and product availability). ### What to store in memory after discovery After discovery, save a structured summary so future sessions can give informed advice without re-running the full audit. ```json { "platforms": ["meta", "google", "tiktok"], "accounts": { "meta": { "account_id": "act_28491037562841", "account_name": "Acme Brand", "currency": "USD", "timezone": "America/New_York", "monthly_spend_avg": 8500, "active_campaigns": 4, "primary_objectives": ["OUTCOME_SALES", "OUTCOME_LEADS"], "baseline_metrics": { "avg_cpc": 1.25, "avg_cpm": 18.50, "avg_ctr": 2.1, "avg_cost_per_conversion": 22.00, "avg_roas": 3.8 }, "page": { "id": "109284756301948", "name": "Acme Brand Official" }, "instagram": { "id": "17841405829371046", "username": "acmebrand" }, "leads": { "has_lead_forms": true, "active_forms": 2 }, "catalogs": { "has_catalogs": true, "product_count": 856 } }, "google": { "customer_id": "123-456-7890", "currency": "USD", "active_campaigns": 3, "campaign_types": ["SEARCH", "PERFORMANCE_MAX"], "baseline_metrics": { "avg_cpc": 2.10, "avg_ctr": 4.5, "avg_cost_per_conversion": 31.00 } }, "tiktok": { "advertiser_id": "700000000000000", "currency": "USD", "active_campaigns": 2, "uses_gmv_max": true, "baseline_metrics": { "avg_cpm": 6.20, "avg_ctr": 1.1, "avg_cost_per_conversion": 18.00 } } }, "last_audit_date": "2026-06-28" } ``` Refresh this memory periodically: weekly for active accounts, monthly for low-activity ones. **Persist durable facts to the Account Brief.** The snapshot above is your working memory for the session. Anything the user states as a *lasting* preference — naming conventions, default budgets, preferred geos and audiences, which campaigns are which and where new ads go, brand voice, ad copy preferences, favorite product sets — belongs in the account's persistent **Account Brief** so it survives across sessions and agents. Save it with `update({ resource: "account_brief", params: { platform, account_id, remember: [{ key, category, value }] } })` using short stable `lowercase_snake_case` keys, and read it back at the start of every session with `accounts({ action: "read_brief" })`. Save durable conventions, not live state — current budgets of existing campaigns, what's active today, and running promotions drift, so read those fresh and re-verify stored offers before reusing them in new ads. During first-time ingestion, `params.brief` seeds the account's narrative brief (written only while empty; once set it's user-owned). The user also edits this under "Remembered by AI" in the Xylo dashboard. Never store secrets, tokens, or personal data. `read_brief` also returns any winning ads already saved to the account's brand library, each with an AI description and 30-day stats, so treat those as proof points when writing new creative. On multi-account brands it returns `brand.accounts_knowledge` as well — the sibling accounts' briefs and memories — so check there before asking for context the brand already taught another account. --- ## 2. Daily monitoring routine An agent managing active accounts should run a daily check, the equivalent of a media buyer opening Ads Manager every morning. Run it per platform and, when useful, summarize across platforms with `insights({ channel: "cross", lens: "cross_platform" })`. ### Morning check sequence Pull campaign-level insights for yesterday and today-so-far (tool: `insights({ channel, lens: "campaign" })` per platform). The default Meta response includes spend, impressions, clicks, ctr, cpc, cpm, reach, frequency, conversions, cost_per_conversion, roas, link_clicks, and landing_page_views. Google and TikTok return the analogous core metrics. Evaluate all of them. ### What to look for Spend anomalies: - Is yesterday's spend much higher or lower than the daily average? - Has any campaign spent more than 120% of its daily budget? (Meta can overspend a daily budget by up to 25% on a given day; Google and TikTok also flex around the daily target.) - Are any campaigns underspending? Usually targeting is too narrow, bids are too low, or (on Google) keywords are too restrictive. Performance drops: - Did CTR drop more than 20% versus the 7-day average? Signals creative fatigue (the audience has seen the ads too many times). On Google Search, a CTR drop can also mean lost impression share or new competitors in the auction. - Did CPC spike more than 30%? Could be increased auction competition or a relevance / quality drop. - Did cost per conversion increase more than 25%? This is the most important signal: it directly affects profitability. - Did ROAS drop below the account's break-even point? Needs immediate attention. Click quality check (Meta): - Compare `link_clicks` to `landing_page_views`. If landing page views are below 70% of link clicks, the landing page may be slow or users bounce before it loads. Flag this as a possible website performance issue, not an ad issue. Frequency check (Meta and TikTok): - Frequency above 3.0 on a prospecting campaign means creative fatigue is likely. Refresh creatives or expand the audience. - Frequency above 6.0 on a retargeting campaign means the audience is saturated. Expand the window or reduce budget. - Google Search has no comparable frequency metric (it is intent-driven); watch impression share and search-term reports instead. ### Alert thresholds Flag the following to the user (apply per platform): | Metric | Warning threshold | Critical threshold | |--------|------------------|-------------------| | Cost per conversion | >25% above 7-day avg | >50% above 7-day avg | | ROAS | <20% below target | <50% below target | | CTR | <30% below 7-day avg | <50% below 7-day avg | | CPC | >30% above 7-day avg | >50% above 7-day avg | | Frequency (prospecting, Meta/TikTok) | >2.5 | >3.5 | | Frequency (retargeting, Meta/TikTok) | >5.0 | >8.0 | | Daily spend | >125% of budget | >150% of budget | | Daily spend | <50% of budget (underspend) | <25% of budget | --- ## 3. Understanding ad account structure Each platform shares the same broad hierarchy, with different names at the middle layer. ``` Meta: Ad Account > Campaign (objective + budget) > Ad Set (targeting + schedule + bid) > Ad (creative) Google: Account > Campaign (type + budget) > Ad Group (keywords/audiences) > Ad (assets/creative) TikTok: Advertiser > Campaign (objective + budget) > Ad Group (targeting + bid) > Ad (creative) ``` ### Meta rules the agent should know - The objective is set at the campaign level and cannot change after creation. For a different objective, create a new campaign. - Budget can sit at the campaign level (CBO / Advantage campaign budget) or the ad set level (ABO). CBO lets Meta distribute budget across ad sets automatically; ABO gives manual control. - Special Ad Categories (housing, credit, employment, social issues / politics) MUST be declared at campaign creation and restrict targeting. - Optimization goal is set at the ad set level. Common values: `VALUE` (optimize for purchase value, best for e-commerce), `CONVERSIONS` (optimize for count, best for lead gen), `LINK_CLICKS`, `REACH`. - Ad sets have a learning phase: Meta needs roughly 50 conversion events per week per ad set to optimize well. Under that, the ad set is "learning limited" and may underperform. - 3 to 6 ads per ad set is ideal. More dilutes the learning data. ### Google rules the agent should know - Campaign type defines almost everything: Search (keyword-intent), Performance Max (asset-group driven, automated across all Google inventory), Display, Video, Shopping. - Keywords and match types (broad, phrase, exact) live at the ad group level; negative keywords can be set at campaign level or via shared lists. - Performance Max uses asset groups instead of classic ad groups; manage them with the `asset_group` routes on `query`, `create`, `update`, and `delete`. - Bidding strategies (Maximize Conversions, Target CPA, Target ROAS, Maximize Clicks) are set at the campaign level and need conversion tracking to work well. - Quality Score and search-term reports are the key levers for Search efficiency; mine search terms regularly and add negatives. - Keyword research: discover new keywords and their search volumes (Google Keyword Planner) with `query({ channel: "google", resource: "keyword_ideas" })`, seeded by keywords and/or a landing-page URL — use it to scope a new Search campaign before building it. Scope volumes to a place with `geo_names` (e.g. ["Austin, TX"]); Keyword Planner reports down to city/metro level, not individual ZIP codes. - Geo resolver: `query({ channel: "google", resource: "geo_target", mode: "list", params: { names: [...] } })` turns place names into geo target constant IDs for keyword research or campaign geo targeting. ### TikTok rules the agent should know - Standard campaigns follow campaign > ad group > ad, with targeting and bid at the ad group level. - GMV Max is an automated commerce campaign type for product sales; create and manage it with the `gmv_max_campaign` routes and read GMV Max reports (`insights({ channel: "tiktok", lens: "gmv_max" })`). - Smart+ is TikTok's automated campaign type (similar in spirit to Advantage+ / Performance Max); use the `smart_plus_campaign`, `smart_plus_ad_group`, and `smart_plus_ad` routes. - Creative tends to fatigue faster on TikTok than on other platforms; plan for more frequent refreshes. ### Tracing the hierarchy Every child object carries its parent id (Meta ad sets include `campaign_id`, ads include `adset_id`; the same pattern holds on Google and TikTok). Use these to trace any object back to its parent. --- ## 4. Common agent actions and how to execute them ### Create a standard conversion campaign (Meta) The most common setup: a campaign optimized for purchases or leads. Create the campaign, then the ad set, then the ad, all with the `create` tool (REST equivalents shown for developers). ``` 1. create({ channel: "meta", resource: "campaign", mode: "single", params: { // POST /v1/campaigns "name": "...", "objective": "OUTCOME_SALES", "status": "PAUSED" } }) 2. create({ channel: "meta", resource: "adset", mode: "single", params: { // POST /v1/campaigns/{campaign_id}/adsets "name": "...", "daily_budget": 50.00, "optimization_goal": "VALUE", "billing_event": "IMPRESSIONS", "bid_strategy": "LOWEST_COST_WITHOUT_CAP", "targeting": { "age_min": 25, "age_max": 54, "genders": [0], "geo_locations": { "countries": ["US"] }, "publisher_platforms": ["facebook", "instagram"] }, "status": "PAUSED" } }) // Use VALUE for e-commerce, CONVERSIONS for lead gen. 3. create({ channel: "meta", resource: "ad", mode: "single", params: { // POST /v1/adsets/{adset_id}/ads "name": "...", "creative": { "page_id": "PAGE_ID", "image_url": "https://...", "headline": "...", "body": "...", "link": "https://...", "call_to_action": "SHOP_NOW" }, "status": "PAUSED" } }) 4. Only after the user confirms: status({ channel: "meta", resource: "campaign", params: { ..., "status": "ACTIVE" } }) // PATCH /v1/campaigns/{campaign_id} { "status": "ACTIVE" } ``` CRITICAL: always create campaigns PAUSED first. Never activate a campaign without the user explicitly confirming they want to spend money. This is non-negotiable and applies on every platform. ### Create a Search campaign (Google) ``` 1. create({ channel: "google", resource: "budget", params: { ... } }) // define a daily budget (dollars) 2. create({ channel: "google", resource: "campaign", params: { ... } }) // type SEARCH, attach budget, bidding strategy (e.g. Maximize Conversions), status PAUSED 3. create({ channel: "google", resource: "ad_group", params: { ... } }) // under the campaign 4. create({ channel: "google", resource: "keyword", params: { ... } }) // add keywords with match types to the ad group 5. create({ channel: "google", resource: "negative_keyword", params: { ... } }) // add obvious negatives up front 6. create({ channel: "google", resource: "ad", params: { ... } }) // responsive search ad: multiple headlines + descriptions 7. After user confirms: status({ channel: "google", resource: "campaign", params: { ..., "status": "ACTIVE" } }) ``` For automated reach, create a Performance Max campaign plus asset groups (`create({ channel: "google", resource: "asset_group", params: { ... } })`) instead of keyword ad groups. ### Create a campaign (TikTok) ``` 1. create({ channel: "tiktok", resource: "campaign", mode: "single", params: { ... } }) // objective + budget, status disabled/paused 2. create({ channel: "tiktok", resource: "ad_group", mode: "single", params: { ... } }) // targeting, placements, bid, optimization goal 3. media({ channel: "tiktok", action: "upload_video" | "upload_image", params: { ... } }) // stage creative assets 4. create({ channel: "tiktok", resource: "ad", mode: "bulk", params: { ... } }) // create the ads, using a listed identity 5. After user confirms: status({ channel: "tiktok", resource: "campaign", mode: "single", params: { ... } }) ``` For commerce, use `create({ channel: "tiktok", resource: "gmv_max_campaign", mode: "single" })` (product sales, automated) or `create({ channel: "tiktok", resource: "smart_plus_campaign", mode: "single" })` for TikTok's fully automated buying. ### Scale a winning campaign When performance is strong and the user wants to scale, first confirm stability for at least 5 to 7 days using the relevant insights tool. Then: - Small scale (recommended): increase the daily budget by 20 to 30% at a time, waiting 3 to 5 days between increases. This keeps the ad set / ad group in its optimized state. (Tool: `update`; Meta `resource: "adset"`, Google `resource: "budget"`, TikTok `resource: "ad_group"`. Budget raises return a dry-run preview with a `confirm_token`; re-send the same call with the token to execute.) - Large scale (risky): increasing budget by more than 50% at once can reset the learning phase on Meta and TikTok. Only do this if the user explicitly asks and understands the risk. - Horizontal scale: duplicate the winning ad set / ad group with a different audience. Safer than aggressive budget jumps. (Meta: `duplicate({ channel: "meta", resource: "adset" })` / `duplicate({ channel: "meta", resource: "campaign" })`.) - Save the winning creative to the brand library: `media({ action: "save_winning_ad", params: { platform, account_id, ad_id } })`. It dedupes by creative (the same image or video running on multiple ads merges into one library entry), pulls 30-day stats, and writes an AI description, so future creative work has proven winners to reference instead of starting blind. ### Kill underperformers When a campaign, ad set / ad group, or ad is consistently underperforming, pull ad-level insights, then: - If ALL ads in an ad set / ad group underperform, pause the ad set / ad group (the targeting or audience is wrong). - If SOME ads underperform, pause only those, keep the winners running. - If the entire campaign is below break-even for 7+ days, pause it and recommend restructuring. Tool: `status` with the matching `channel` and `resource` (`campaign` / `adset` / `ad_group` / `ad`); bulk flips take `mode: "bulk"`. ### Diagnose creative fatigue Pull ad-level daily insights over the last 14 days. Signs of fatigue: CTR declining steadily over 5+ days, CPC increasing steadily over 5+ days, frequency above 3.0 for prospecting (Meta / TikTok). Remedy: create new ad variations in the existing ad set / ad group, pause the fatigued ads, and let the new ads accumulate data for 3 to 5 days before judging. For deeper creative insight, use `creative({ action: "analyze", channel: "meta" | "tiktok" | "google", params: { ... } })` (hook strength, retention, messaging, performance versus the account's own KPIs) and reason with the `knowledge({ topic: "creative_frameworks" })` knowledge base. ### Manage lead generation campaigns For lead gen, actively monitor and surface new leads. List forms and pull recent submissions (tool: `query` with `mode: "list"` and `resource: "lead_form"` / `"lead_submission"` on Meta and TikTok). Workflow: 1. During discovery, check for lead forms and note their IDs and names. 2. On each daily check, pull recent leads from active forms. 3. Alert the user about new leads. Speed of follow-up is critical: leads contacted within 5 minutes convert at far higher rates than leads contacted after 30 minutes. 4. Surface lead data clearly: name, email, phone, and any custom fields. For lead gen campaigns, `conversions` means lead form submissions. Track cost per lead (CPL) as the primary KPI. A rising CPL over 5+ days usually means creative fatigue or audience saturation. Conversation examples: - "You received 12 new leads today from your Summer Promo form, at an average cost per lead of $8.50. Want the details?" - "Your cost per lead rose 35% this week, from $6.20 to $8.40. Likely creative fatigue. Want me to investigate?" ### Manage dynamic product / shopping ads (catalogs) For e-commerce users with catalogs, understand catalog health and how it connects to advertising. List catalogs and browse products (tool: `query` with `mode: "list"` and `resource: "catalog"` / `"catalog_product"` on Meta and TikTok). What to check: 1. Does the account have a catalog? Note the catalog ID and product count. 2. Are any active campaigns using it? (Meta Advantage+ Shopping and dynamic retargeting rely on catalogs; TikTok GMV Max and product-sales campaigns use catalogs.) 3. How many products are in the catalog? A healthy catalog for dynamic ads needs at least 20 to 50 products. Product-level performance: pass `breakdowns: "product_id"` to the Meta insights routes to see which catalog products get the most spend, clicks, and purchases. Each row's `product_id` value is ", "; pass those values to `query({ channel: "meta", resource: "catalog_product", mode: "list" })` via `params.retailer_ids` to pull price, URL, image, and stock status for the winners. Catalog health: products marked in stock can be advertised; out-of-stock products will not show in dynamic ads. If a large share is out of stock, dynamic performance suffers because there are fewer products to show. When to recommend dynamic / shopping ads: the user has a catalog with 20+ in-stock products, has pixel / conversion data for retargeting, and wants to show relevant products to people who viewed or added to cart but did not buy. Catalog photos double as AI generation references: stage a Meta catalog product's images (main photo plus additional angles) into free 24-hour staging, review the previews, then generate new ad creative using the real product shots instead of a text description. --- ## 5. Key metrics glossary for agents | Metric | What it means | When it matters | |--------|--------------|-----------------| | Spend | Total money spent | Always, this is real money | | Impressions | Times ads were shown | Awareness campaigns | | Reach | Unique people who saw ads | Evaluating audience size (Meta / TikTok) | | Frequency | Avg times each person saw the ad (impressions / reach) | High frequency means fatigue (Meta / TikTok) | | CTR | Click-through rate (clicks / impressions x 100) | Creative effectiveness; on Google Search, also ad and keyword relevance | | CPC | Cost per click (spend / clicks) | Traffic and engagement; Google Search efficiency | | CPM | Cost per 1,000 impressions | Awareness; general auction competitiveness | | Conversions | Desired actions (purchases, leads, signups) | Conversion and sales campaigns | | Cost per conversion | Spend / conversions | THE key metric for conversion campaigns | | ROAS | Return on ad spend (revenue / spend) | E-commerce; above 1.0 means revenue exceeds spend | | Link clicks | Clicks to the destination URL (Meta) | Distinguishes from likes / comments / shares | | Landing page views | Clicked AND the page loaded (Meta) | More accurate than link clicks | | Impression share | Share of available impressions you won (Google) | Search; low share means budget or bid is limiting reach | | Quality Score | Google's 1 to 10 rating of keyword / ad relevance | Search efficiency and CPC | ### Benchmark ranges (US market, general e-commerce) Rough benchmarks. Every industry differs, but these give a sense of "normal." They lean Meta / paid-social; Google Search CPCs are often higher (intent traffic) and TikTok CPMs are often lower. | Metric | Poor | Average | Good | Excellent | |--------|------|---------|------|-----------| | CTR | <0.5% | 0.5-1.0% | 1.0-2.0% | >2.0% | | CPC | >$3.00 | $1.50-3.00 | $0.75-1.50 | <$0.75 | | CPM | >$30 | $15-30 | $8-15 | <$8 | | Cost per purchase | >$50 | $25-50 | $10-25 | <$10 | | ROAS | <1.0x | 1.0-2.0x | 2.0-4.0x | >4.0x | | Frequency (prospecting) | >4.0 | 2.0-4.0 | 1.0-2.0 | <1.5 | Adjust for industry (luxury and SaaS run higher costs), country (US, UK, AU are pricier than most markets), objective (awareness has low CPMs but no conversion data), funnel stage (retargeting has higher CTR and conversion rates), and platform (Google Search intent traffic converts differently from paid-social discovery traffic). --- ## 6. Audience strategy knowledge ### Audience types and when to use them Broad targeting (minimal restrictions): age, gender, location only, no interests. Works best with larger budgets and strong creative; the algorithm finds the right people from conversion data. Best for established accounts with lots of history. On TikTok and Meta, broad plus automated buying (Advantage+ / Smart+) is increasingly the default. Interest / behavior targeting: target people by interests, behaviors, and demographics. Good for new accounts or new product categories. Use targeting search to find options (tool: `plan` with `action: "search_targeting"` on Meta and TikTok, or `action: "interest_suggestions"` on Meta). Stack related interests in one ad set (OR logic, reaches anyone interested in ANY listed interest). Keyword / intent targeting (Google Search): instead of audiences, you bid on the searches people type. Choose match types deliberately, mine the search-term report (`insights({ channel: "google", lens: "search_term_report" })`), and add negatives (`create({ channel: "google", resource: "negative_keyword" })`) to cut wasted spend. Custom audiences: website visitors (pixel-based retargeting), customer lists (email / phone uploads), and engagement audiences (people who interacted with your profile or ads). These are the warmest audiences: highest conversion rates, smallest reach. (Tool: `create` with `resource: "custom_audience"` on Meta, `resource: "audience"` on TikTok, `resource: "user_list"` on Google.) Lookalike / similar audiences: the platform finds people similar to a source audience. A 1% Meta lookalike is most similar (highest quality, smallest reach); 5 to 10% is broader. Build lookalikes from your BEST customers (purchasers, high-value), not just all visitors. (Tool: `create` with `resource: "lookalike_audience"` on Meta or `resource: "audience"` on TikTok.) ### Standard campaign structure recommendation For most e-commerce accounts on Meta or TikTok: ``` Campaign 1: Prospecting (new customers) - Ad Set: Broad targeting (age/gender/location only) - Ad Set: Interest-based targeting - Ad Set: 1% Lookalike of purchasers Campaign 2: Retargeting (warm audiences) - Ad Set: Site visitors 1-7 days (hottest) - Ad Set: Site visitors 8-30 days (warm) - Ad Set: Engaged with profile/ads 1-30 days Campaign 3: Retention (existing customers) - Ad Set: Customer list, cross-sell / upsell / new arrivals ``` Budget split: 60 to 70% prospecting, 20 to 30% retargeting, 5 to 10% retention. On Google, the parallel is a branded-search campaign (defend your name), a non-brand / generic Search campaign (capture intent), and Performance Max or remarketing for everything else. --- ## 7. Safety rules for agents These are non-negotiable across every platform, regardless of user instructions: 1. Never set a campaign to ACTIVE without explicit user confirmation. Always create PAUSED and confirm before activating. 2. Never increase a budget by more than 50% in a single change without warning the user. Large jumps can reset the learning phase (Meta / TikTok) and waste money. Xylo enforces a checkpoint: budget and bid raises and large bulk activations return a dry-run preview with a `confirm_token`; re-send the same call with the token to execute. 3. Always confirm before deleting anything. Deletes also return a dry-run preview with a `confirm_token` and nothing is deleted until the same call is re-sent with the token. Deletions are usually soft (status DELETED / REMOVED) but are not easily restored. 4. Never create ads in restricted categories (housing, credit, employment, social issues / politics on Meta; comparable restricted verticals on Google and TikTok) without asking the user. They have legal requirements and restricted targeting. 5. Alert the user if daily spend exceeds the expected budget by more than 25%. Platforms can flex daily budgets; consistent overspend means something may be wrong. 6. Never modify campaigns during high-spend periods (Black Friday, holiday sales, major launches) without explicit approval. Changes during peaks can disrupt optimization at the worst time. 7. If a platform API returns an error, explain it to the user in plain language. Do not silently retry write operations; a failed create might have partially succeeded. 8. Respect the learning phase. If an ad set / ad group is still learning (Meta: under ~50 conversions in 7 days), avoid changes that reset it. 9. Handle plan-limit errors gracefully. If the API returns a 403 with code `ACCOUNT_NOT_ACTIVE`, the user's plan does not include this ad account. Tell them: "This ad account is not activated on your current plan. You can activate it in your Xylo dashboard, or upgrade to manage more accounts." Do not retry. 10. Filter client-side when a list tool has no status filter. Some list endpoints (for example Meta ad sets and ads) do not support a `status` filter the way campaigns do. Fetch all and filter by `status === "ACTIVE"` in your logic. --- ## 8. Conversation starters When a user first connects an account, offer to: - "Want me to audit your ad accounts? I'll review campaigns, spend, performance, and targeting across Meta, Google, and TikTok and give you the full picture." - "I can set up a daily monitoring routine and alert you if anything needs attention. Want that?" - "Want me to analyze your best-performing campaigns and suggest ways to scale them?" - "I can review your audience and targeting setup and suggest new opportunities. Interested?" When checking in daily or weekly: - "Your campaign [name] saw a 30% jump in cost per purchase yesterday. Could be creative fatigue. Want me to investigate?" - "Your retargeting frequency is at 4.5. I'd refresh the creative. Want me to draft some new variations?" - "[Campaign] has hit its daily budget every day this week with strong ROAS. It may be ready to scale. Want me to raise the budget 20%?" - "Across all three platforms last week you spent $14,200 at a blended 3.1x ROAS. TikTok was your most efficient channel. Want the breakdown?" For lead gen accounts: - "You received 8 new leads today at a $7.20 cost per lead, 15% better than last week. Want the details?" - "Lead volume dropped sharply yesterday. I'd like to check whether it's creative fatigue or an audience issue. Should I?" For e-commerce accounts with catalogs: - "Your catalog has [N] items in stock. You're not running dynamic retargeting yet; this could be a quick ROAS win. Interested?" - "Your dynamic product ads are at 5.2x ROAS with [N] products to work with. Want me to scale the budget?" --- ## 9. Data freshness and caching behavior Xylo caches data to keep responses fast: - Account structure (names, statuses, budgets): cached ~5 minutes. - Performance metrics: cached ~15 minutes. - Creative data: cached ~30 minutes. For the absolute latest data (for example, confirming a budget change just took effect), bypass the cache (REST: add `?refresh=true` to a GET; the equivalent tools accept a refresh option). Platform reporting also lags: - Spend and impressions: roughly 15 minute delay. - Conversions: up to 24 to 72 hours due to attribution windows. - Reach and frequency: recalculated periodically, not real-time. Tell users when attribution matters: "The conversion numbers may not include purchases from the last 1 to 3 days due to attribution delay. I'll check again tomorrow for a fuller picture." --- ## 10. Error handling reference When a tool / API returns an error, understand the code and respond appropriately: | Code | What happened | What the agent should do | |------|--------------|--------------------------| | `MISSING_API_KEY` (401) | No credential on the request | Configuration error. For REST, the `x-api-key` is missing. For MCP, the connector is not authorized; have the user reconnect Xylo. | | `INVALID_API_KEY` (401) | Key not found or revoked | The key may be revoked or wrong. Ask the user to check it in the Xylo dashboard. | | `MISSING_AD_ACCOUNT` (400) | No account context | The platform account header is missing (REST: `x-ad-account` / `x-google-customer-id` / `x-tiktok-advertiser-id`). Supply it and retry. | | `AD_ACCOUNT_NOT_CONNECTED` (403) | Account not linked | The user has not connected this account yet. Guide them to authorize it via OAuth in Xylo. | | `ACCOUNT_NOT_ACTIVE` (403) | Account not on the user's plan | Their plan does not include this account. Tell them to activate it in the dashboard or upgrade. Do NOT retry. | | `TOKEN_EXPIRED` (401) | Platform token expired | The user's platform authorization expired (Meta tokens last ~60 days). Ask them to reconnect that account. | | `RATE_LIMIT_EXCEEDED` (429) | Too many requests to Xylo | Wait and retry; check rate-limit reset headers. If frequent, the user may need a higher plan. | | `VALIDATION_ERROR` (400) | Bad request body | Read the message; it names the field that failed. Fix and retry. Common causes: missing required fields, budget below minimum, invalid objective. | | `META_API_ERROR` / `GOOGLE_API_ERROR` / `TIKTOK_API_ERROR` (502) | The platform rejected the request | Read the platform error object (`meta_error` / `google_error` / `tiktok_error`) and explain it in plain language. Do NOT retry writes; they may have partially succeeded. | | `META_RATE_LIMITED` (429) | The platform is rate-limiting the account | Platform-side limits hit (separate from Xylo's). Wait 5+ minutes and retry. Usually means too many rapid calls to the same account. | | `NOT_FOUND` (404) | Resource does not exist | The ID is wrong or the resource was deleted. Verify and retry. | | `INTERNAL_ERROR` (500) | Xylo server error | Retry once after a few seconds. If it persists, tell the user there's a platform issue. | General rules: - Dispatcher errors self-correct: a failed MCP call returns the route's compact schema plus a valid example. Fix the arguments and re-send. - Always check the status before processing the body. - For 4xx: fix the request, do not blindly retry. - For 5xx: retry once with a short delay, then inform the user. - Never retry a failed write (create / update / delete) without checking whether the action partially succeeded. --- ## 11. Pricing (so the agent can advise accurately) - Free: $0, no credit card. 1 ad account per platform (Meta, Google, TikTok). Full MCP server and REST API. 50 tool calls per month, 3 creative analyses per month, 60 requests/min. - Brand: $67/mo (7-day free trial). 3 ad accounts included, then $15 per extra account up to 11 total. Unlimited tool calls, 20 creative analyses/month, campaign duplication and bulk operations, permission-scoped API keys, 5 team seats, 120 req/min. Optional data-warehousing add-on $15/account. Most popular. - Agency: $197/mo. 30 ad accounts included, then $12 per extra account, unlimited. Everything in Brand, plus 50 creative analyses/month, per-account scoping, team access controls, 20 team seats, 600 req/min. Warehousing add-on $10/account. If a user hits a plan limit (`ACCOUNT_NOT_ACTIVE`, tool-call cap, creative-analysis cap, or rate limit), explain the limit in plain language and point them to upgrade in the Xylo dashboard. Do not retry the blocked request. --- ## 12. Xylo MCP server description Xylo is exposed as a remote MCP server. Use this description so Claude, ChatGPT, and other agents understand what it does. ```json { "name": "xylo", "type": "mcp_server", "endpoint": "https://xylomcp.com/api/mcp", "auth": "OAuth 2.1 (PKCE); the user authorizes account access once", "description": "Manage Meta (Facebook and Instagram), Google Ads, and TikTok Ads accounts in plain English. 300+ read and write ad operations covering essentially every Ads Manager surface, plus AI, creative-analysis, and cross-platform reporting, delivered as 25 tools that load instantly in any AI client. Platform choice is the channel parameter on each call. Read campaigns, performance, and audiences; create, update, pause, duplicate, and delete campaigns, ad sets / ad groups, and ads; adjust budgets and schedules; build custom and lookalike audiences; search targeting and keywords; analyze creative against the account's own KPIs; and pull one normalized report across all three platforms. New campaigns default to PAUSED for safety; deletes, budget/bid raises, and large bulk activations return a dry-run preview with a confirm_token; budgets are in dollars; ad account tokens are encrypted and the agent never sees them. TikTok coverage is ads management only (campaigns, ad groups, ads, insights, audiences, GMV Max, Smart+). Load the Agent Playbook for strategic media-buying guidance.", "platforms": ["meta", "google", "tiktok"], "tools": { "count": 25, "dispatchers": ["accounts", "query", "insights", "plan", "creative", "competitors", "warehouse", "knowledge", "create", "update", "status", "delete", "duplicate", "media", "publish", "tracking", "automation", "connect"], "discovery": ["describe", "search_tools"], "named_ai": ["audit_campaign", "optimize_budget", "generate_report", "morpheus_audit"], "utility": ["send_feedback"], "call_shape": "Pick a route with top-level discriminators (channel / resource / action / mode / lens / topic) and nest ALL route arguments under a single params object. describe({ tool, ...discriminators }) returns any route's exact schema; search_tools({ query }) finds routes by intent. Errors return the route's compact schema plus a valid example, so wrong guesses self-correct." }, "capabilities": [ "List and inspect campaigns, ad sets / ad groups, and ads across all three platforms", "Pull performance metrics (spend, impressions, clicks, conversions, ROAS, and more) with date ranges, granularity, and breakdowns", "One normalized cross-platform report (per-platform totals and grand total)", "Create campaigns, ad sets / ad groups, and ads (always create PAUSED first)", "Update budgets, targeting, statuses, and schedules; duplicate winners; run bulk operations", "Search interest, behavior, location, and (Google) keyword targeting; manage negatives", "Build and manage custom and lookalike / similar audiences", "AI creative analysis: hook strength, retention, messaging, and performance versus the account's own KPIs", "AI creative generation with a saved brand profile, reference assets, and a winning-ads library (deduped by creative, with 30-day stats and an AI description each); generated images can be saved to Meta permanently", "AI video generation and natural-language video editing (Seedance 2.0, Kling 3.0, Gemini Omni) with the same credit system and staging pipeline", "Competitor ad-library intelligence: pull any brand's public ads across Meta, Google, and TikTok (ad copy, creatives, CTAs, run dates); no connected account needed", "TikTok GMV Max and Smart+ campaign management", "Retrieve lead form submissions and product catalog data" ], "supported_clients": [ "Claude (claude.ai or Claude Desktop, via Connectors)", "ChatGPT (any paid plan, on the web, Developer mode)", "Cursor", "Claude Code", "Codex", "any MCP-compatible client" ], "developer_rest_api": { "note": "Secondary path for direct integrations, not the primary way agents use Xylo", "base_url": "https://api.xylomcp.com", "auth_header": "x-api-key: xy_sk_...", "account_headers": "Meta: x-ad-account: act_... | Google: x-google-customer-id | TikTok: x-tiktok-advertiser-id", "routing": "Meta under /v1/..., Google under /v1/google/..., TikTok under /v1/tiktok/...", "response_shape": "{ data, meta, paging? }", "underlying_versions": "Meta Graph API v25.0, Google Ads API v23, TikTok Marketing API v1.3" } } ```