MMetadata /docs
Docs/Tools/create_campaign

create_campaign

Create multi-channel advertising campaigns for LinkedIn, Facebook, Instagram, Google Ads, Reddit, and Microsoft Ads using the platform's "Precision Optimization" (1×1×1) model —…

Writes campaigns

Creates or changes something in the account. Put it behind whatever review your agent uses.

What it does

Create multi-channel advertising campaigns for LinkedIn, Facebook, Instagram, Google Ads, Reddit, and Microsoft Ads using the platform's "Precision Optimization" (1×1×1) model — Metadata's signature approach. Every audience×ad×offer combination is tested as its OWN isolated experiment (each experiment = exactly 1 audience × 1 ad × 1 offer); you pass per-channel lists of audiences, ads, and offers and the backend creates one experiment per combination. Platform product copy: "Metadata's signature approach with maximum budget control and fastest learning through separate testing of each combination." This is the DEFAULT structure when the user hasn't chosen one. Sets channel.structureType=METADATA (no WizNativeAdContainer).

                    KEYWORDS (for tool discovery — many users ask by the math, not the product name): 1x1x1, 1×1×1, "1x1x1 campaign", "one by one by one", Precision Optimization, separate testing of each combination, isolated per-combination experiments, maximum budget control, fastest learning.

                    NAMING CONVENTION (from the platform UI's "Campaign Structure" selector — match these exact labels):
                      • "Precision Optimization (1x1x1)" = THIS tool (`create_campaign`). Each experiment isolates one audience×ad×offer cell; the platform builds one per combination. Metadata's signature approach; the DEFAULT.
                      • "Channel First Structure (NxNxN)" = the OTHER tool, `create_native_structure_campaign` (the UI also shows it as "Native Structure" / "Platform-First Structure"). Audiences/ads/offers are grouped in the ad platform's NATIVE structure (WizNativeAdContainer) and optimized together by the platform (~1 experiment per channel).
                    Routing anchor: "precision" / "1x1x1" → this tool; "native" / "channel first" / "platform first" / "NxNxN" → create_native_structure_campaign. (structureType=METADATA here, NATIVE there — and that lines up, because "native" means the native-platform structure.)

                    ════════════════════════════════════════════════════════════════════════════════
                    ⚠️ TWO CAMPAIGN-CREATION TOOLS EXIST — READ BEFORE PICKING ONE ⚠️
                    ════════════════════════════════════════════════════════════════════════════════
                    🔴 REMEMBER — HOW TO CHOOSE THE STRUCTURE (the user's decision always wins):
                      1. If the user explicitly names one, RESPECT IT — "precision" / "Precision Optimization" / "1x1x1" → create_campaign (this tool); "native" / "Native Structure" / "Channel First" / "Platform-First" / "NxNxN" → create_native_structure_campaign.
                      2. ELSE, if the request involves MANY ads AND audiences (Precision Optimization makes one experiment per combination — a large experiment count), ASK the user which structure they want before creating — do not guess.
                      3. OTHERWISE, DEFAULT to Precision Optimization (1×1×1) → this tool (create_campaign).
                    The two build structurally different, non-swappable campaigns — so once the user decides, respect that decision for the rest of the campaign.

                    USE THIS TOOL (`create_campaign`) — "Precision Optimization" (1×1×1) — WHEN:
                      • The user says "Precision Optimization", "precision", "1x1x1", "1×1×1", "separate testing of each combination", or wants each combination tested in its own isolated experiment.
                      • The user gives per-channel lists of audiences/ads/offers and wants the platform to test every combination separately (one experiment per audience×ad×offer).
                      • The user wants maximum budget control / fastest per-combination learning.
                      • No structure was specified — this is the DEFAULT.

                    USE `create_native_structure_campaign` ("Channel First" / "Native Structure", N×N×N) INSTEAD — DO NOT USE THIS TOOL — WHEN:
                      • The user says "native", "Native Structure", "Channel First Structure", "channel-first", "Platform-First Structure", "platform-first", "NxNxN", "N×N×N", "WizNativeAdContainer", or asks for the traditional / hierarchical / native-platform structure.
                      • The user wants the ad platform's native structure to group and optimize audiences/ads/offers together (~1 experiment per channel, unified reporting) rather than one isolated experiment per combination.
                      • The user is migrating a campaign FROM "Precision Optimization" (1×1×1) TO the native "Channel First" structure.
                      Do not silently call this tool when the user has signalled Channel-First / native intent — the schemas and resulting platform state are different and not swappable after creation.

                    Apply the structure-selection rule above: respect an explicit "precision"/"native" choice; if the user didn't choose, ASK only when there are MANY ads AND audiences; otherwise default to Precision Optimization (1×1×1, this tool).
                    ════════════════════════════════════════════════════════════════════════════════

                    WHEN TO USE:
                    - Create multi-channel marketing campaigns with unified configuration
                    - Set up campaigns with specific start/end dates and budget groups
                    - Configure Lead Generation or Brand Awareness campaigns
                    - Organize ads into groups with specific targeting and offers
                    - Set up Google Ads campaigns with keyword targeting

                    CAMPAIGN TYPES:
                    1. "Lead Gen" - Lead generation campaigns
                    2. "Brand Awareness" - Brand awareness campaigns

                    ⚠️ CRITICAL OFFER TYPE RULE:
                    - "Lead Gen" campaigns: ONLY Lead Gen (LG) form offers allowed. Landing Page (LP) offers are FORBIDDEN.
                    - "Brand Awareness" campaigns: Both LG and LP offers allowed. No restriction.

                    ⚠️ CRITICAL OFFER-CHANNEL PAIRING RULE (silent failure if violated) ⚠️
                    Lead Gen offers are CHANNEL-LOCKED at creation time (the channel was set on create_update_offer via data.channel). An offer_id created with channel="LINKEDIN" CANNOT be assigned to facebook.offers / instagram.offers / google.offers — and vice versa. This server DOES NOT validate the pairing and will RETURN SUCCESS on a mis-wired campaign that cannot actually serve. The only way the user finds out is when the campaign produces zero impressions in the platform.

                    HARD RULES (verify each offer_id BEFORE submitting):
                    1. linkedin.offers MUST contain ONLY offer_ids whose creating call set data.channel="LINKEDIN" (or Landing Page offer_ids, which have no channel and are universal).
                    2. facebook.offers MUST contain ONLY offer_ids with data.channel="FACEBOOK" (or Landing Page offer_ids).
                    3. instagram.offers MUST contain ONLY offer_ids with data.channel="INSTAGRAM" or "FACEBOOK" (or Landing Page offer_ids).
                    4. google.offers MUST contain ONLY Landing Page offer_ids — Google Ads does NOT support Lead Gen forms. Putting any Lead Gen offer_id in google.offers is a HARD FAILURE.
                    5. reddit.offers MUST contain ONLY Landing Page offer_ids — Reddit does NOT support Lead Gen forms (create_update_offer rejects channel="REDDIT"). Putting any Lead Gen offer_id in reddit.offers is a HARD FAILURE.
                    6. microsoft.offers MUST contain ONLY offer_ids with data.channel="MICROSOFT_ADS" (or Landing Page offer_ids). Unlike Google, Microsoft Ads DOES accept Lead Gen offers, but only when channel-locked to MICROSOFT_ADS.
                    7. If the user's campaign requires Lead Gen on multiple channels, you MUST have called create_update_offer SEPARATELY for each channel (one call per channel per concept). Cross-channel reuse of a Lead Gen offer_id WILL break the campaign even though this API returns success.
                    8. If you cannot remember which channel an offer_id was created for, call get_offer(name=<offer_name>) first and read the channel field — DO NOT GUESS.

                    REQUIRED FIELDS:
                    - campaignType: "Lead Gen" or "Brand Awareness"
                    - name: Unique campaign name
                    - startDate / endDate: YYYY-MM-DD format
                    - budgetGroup: Budget group name (e.g., "BoFu", "ToFu", "Brand")
                    - Per-channel dailyBudget (optional, min $10): the channel's daily spend in USD. Set it whenever a budget split was approved (monthly channel budget / 30); a channel without it keeps the platform default of $50/day.
                    - At least one channel must be configured

                    CHANNEL-SPECIFIC CONFIGURATION:

                    ⚠️ AUDIENCES vs TARGET GROUPS — CRITICAL DISTINCTION:
                    - "audiences": standard Metadata audiences (Firmographic, Bombora Intent, Retargeting, LinkedIn/Facebook Native, etc.)
                    - "target_groups": Targeting Groups (also called Target Groups) created in the platform's Targeting Groups section.
                    Both are arrays of names (strings). Send each type in its own field — do NOT mix them.
                    If the user mentions a "Targeting Group" or "Target Group", it goes in "target_groups", NOT in "audiences".

                    ⚠️ ADS — SEPARATE (default) vs BUNDLED INTO ONE GROUP (opt-in):
                    The "ads" object has two slots and they map to two different platform structures:
                    - "ads.list": a flat array of ad IDs. Each id is sent as its own request, so a list of N ids
                      produces N separately managed ads, NOT one bundle. THIS IS THE DEFAULT — put ads here
                      unless the user explicitly asks for ad groups.
                    - "ads.groups": an array of {name, ads:[ids]} objects. Each object bundles its ad IDs into ONE named
                      ad group. Use this ONLY when the user explicitly wants ads grouped together
                      (e.g. "put these in an ad group", "group these ads"). LinkedIn has no ad-group concept — use list only.
                    You may send both: ads in "list" stay separate, ads in "groups" get bundled.
                    (Note: the platform wraps every ad in an ad-group record server-side, single ads included. That is
                    outside this tool's control and does not change the two shapes above.)

                    LINKEDIN (optional):
                    - audiences: Array of audience names (required if linkedin included)
                        Example: ["Test Native Audience", "EU Countries"]
                    - target_groups: Array of Targeting Group names
                        Example: ["My Target Group 1"]
                    - ads: Object with ad organization (required if linkedin included)
                        - list: Array of ad IDs, each sent as its own request (default). Example: [156502, 156485]
                          (LinkedIn has no ad groups — always use list.)
                    - offers: Array of offer IDs (required if linkedin included)
                        Example: [57538, 57504]

                    FACEBOOK (optional):
                    - audiences: Array of Facebook audience names (required if facebook included)
                        Example: ["fb-test", "automation-fb-retargeting-event-stage-blue"]
                    - target_groups: Array of Targeting Group names
                    - ads: Object with ad organization (required if facebook included)
                        - list: Array of ad IDs, each sent as its own request (DEFAULT — use this)
                        - groups: Array of ad group objects [{"name": str, "ads": [ids]}] — bundles ads into
                          a named ad group. ONLY when the user explicitly asks for grouped ads.
                    - offers: Array of offer IDs (required if facebook included)

                    INSTAGRAM (optional):
                    - audiences: Array of Instagram audience names (required if instagram included)
                    - target_groups: Array of Targeting Group names
                    - ads: Object with ad organization (required if instagram included)
                        - list: Array of ad IDs, each sent as its own request (DEFAULT — use this)
                        - groups: Array of ad group objects [{"name": str, "ads": [ids]}] — bundles ads into
                          a named ad group. ONLY when the user explicitly asks for grouped ads.
                    - offers: Array of offer IDs (required if instagram included)
                    - Often shares same audiences and offers as Facebook

                    GOOGLE ADS (optional):
                    - keywords: Object with keyword organization (required if google included)
                        - groups: [{"name": "CRM Keywords", "keywords": ["crm software", "lead gen tools"], "match_type": "PHRASE"}]
                          Each group also accepts "keyword_ids": [<existing library keyword IDs from list_keywords>] and "match_type": PHRASE|BROAD|EXACT (default PHRASE).
                    - audiences: Array of Google audience names (required if google included)
                        Example: ["SUP_SF_All-Customers-Contacts_ALL_3"]
                    - target_groups: Array of Targeting Group names
                    - ads: Object with ad organization (required if google included)
                        - list: [175258] — ad IDs each sent as their own request (DEFAULT — use this)
                        - groups: [{"name": "GOAT", "ads": [175260, 175259]}] — bundles ads into a named
                          ad group. ONLY when the user explicitly asks for grouped ads.
                    - offers: Array of offer IDs (required if google included)
                    - negative_keyword_lists: Array of negative keyword list names (optional)
                        Example: ["Competitor Brands", "Low Intent Keywords"]
                        These are assigned to the Google Ads channel AFTER campaign creation.
                        List names must match existing negative keyword lists (use list_negative_keywords_list to find them).

                    REDDIT (optional):
                    - audiences: Array of Reddit audience names (required if reddit included)
                    - target_groups: Array of Targeting Group names (Reddit Target Groups are created via create_reddit_target_group)
                    - ads: Object with ad organization (required if reddit included)
                        - list: Array of ad IDs, each sent as its own request. Reddit ads
                          are created via create_update_image_ad / create_update_video_ad with channels=["REDDIT"].
                          (Like LinkedIn, always use list — no ad groups.)
                    - offers: Array of offer IDs (required if reddit included). Landing Page
                      offers ONLY — Reddit does not support Lead Gen forms.
                    - Channel settings (objective, allow comments, placements, conversion pixel)
                      get UI-equivalent defaults on creation — adjust them afterwards with
                      update_reddit_channel_settings.

                    MICROSOFT ADS (optional):
                    - Search channel — mirrors Google Ads structurally. The platform pairs
                      MICROSOFT_ADS with GOOGLE_ADS for the TARGET_SPEND bid default.
                    - keywords: Object with keyword organization (required if microsoft included)
                        - groups: [{"name": "CRM Keywords", "keywords": ["crm software", "lead gen tools"], "match_type": "PHRASE"}]
                          Each group also accepts "keyword_ids": [<existing library keyword IDs from list_keywords>] and "match_type": PHRASE|BROAD|EXACT (default PHRASE).
                    - audiences: Array of Microsoft Ads audience names (required if microsoft included)
                    - target_groups: Array of Targeting Group names
                    - ads: Object with ad organization (required if microsoft included)
                        - list: Array of ad IDs, each sent as its own request (DEFAULT)
                        - groups: [{"name": "MS Group A", "ads": [ids]}] — bundles ads into a named
                          ad group. ONLY when the user explicitly asks for grouped ads.
                    - offers: Array of offer IDs (required if microsoft included). Lead Gen offers
                      must be MICROSOFT_ADS-locked (created with data.channel="MICROSOFT_ADS");
                      Landing Page offers are universal.
                    - negative_keyword_lists: Array of negative keyword list names (optional)
                        Example: ["Competitor Brands", "Low Intent Keywords"]
                        Assigned to the Microsoft Ads channel after creation. Names must match
                        existing lists (use list_negative_keywords_list to find them).

                    VALIDATION:
                    - Campaign name must be unique
                    - Start date must be before end date
                    - All referenced ad IDs, offer IDs, and audience names must exist
                    - If a channel is included, its required fields (audiences, ads, offers) must be provided
                    - ⚠️ Lead Gen campaigns with Landing Page offers MUST be rejected

                    OFFER VERIFICATION (Lead Gen only):
                    1. Call get_offer to check offer types before campaign creation
                    2. If any offer is Landing Page → reject and suggest switching to Brand Awareness or replacing with LG offers

                    RESPONSE: Returns campaign_id, campaign_url, status, configured_channels, per-channel
                    details, optimization_group (id + tag_name), and a `full_response` payload with the
                    complete wizard state. On partial failures, returns success=false plus an `errors[]`
                    list — the campaign shell is still created and partial work is preserved.
                    Campaign URL: https://platform.metadata.io/hub/advertise/campaigns/{campaign_id}

                    BID STRATEGY (automatic — no user input needed):
                    Every enabled channel is set to a safe "auto" default immediately after creation so
                    the campaign is launch-ready:
                      - LinkedIn / Facebook / Instagram → AUTO_BID
                      - Google Ads / Microsoft Ads      → TARGET_SPEND (device modifiers reset to 0)
                      - Reddit                          → follows the objective, mirroring the platform UI:
                        Lead Gen campaigns force the CLICKS (Traffic) objective + AUTO_BID; Brand
                        Awareness keeps the platform default IMPRESSIONS objective + MANUAL_BID.
                        Change objective/bid afterwards with update_reddit_channel_settings.
                    This happens regardless of account type and regardless of
                    campaign goal (CPL / CTR). The user can still override bid strategy later via the
                    platform UI or a dedicated tool.

                    EXAMPLE (Lead Gen, multi-channel):
                    create_campaign(campaign_data={
                        "campaignType": "Lead Gen",
                        "name": "Q1_Multi_Channel_2025",
                        "startDate": "2025-08-01",
                        "endDate": "2025-09-30",
                        "budgetGroup": "BoFu",
                        "linkedin": {
                            "audiences": ["Test Native Audience", "EU Countries"],
                            "ads": {"list": [156502, 156485]},
                            "offers": [57538, 57504]
                        }
                    })

                    EXAMPLE (Brand Awareness, single-channel):
                    create_campaign(campaign_data={
                        "campaignType": "Brand Awareness",
                        "name": "LinkedIn_Brand_Jan2025",
                        "startDate": "2025-01-15",
                        "endDate": "2025-02-15",
                        "budgetGroup": "Brand",
                        "linkedin": {
                            "audiences": ["Professional Audience"],
                            "ads": {"list": [173669, 171805]},
                            "offers": [57538]
                        }

                        CAMPAIGN URL FORMAT:
                        - All successful campaign creations return a direct URL to the campaign
                        - URL format: https://platform.metadata.io/hub/advertise/campaigns/{campaign_id}
                        - Use this URL to navigate directly to the campaign in the platform
                        - Campaign URL is always included in successful responses
                        - Provides immediate access to campaign management and monitoring

                        BEST PRACTICES:
                        1. Use descriptive, unique campaign names with dates or identifiers
                        2. Ensure all referenced assets (ads, offers, audiences) exist before campaign creation
                        3. Plan campaign dates appropriately with buffer time for setup
                        4. Group related ads together for better organization and reporting
                        5. Use consistent naming conventions for ad groups across channels
                        6. Test with single-channel campaigns before creating multi-channel campaigns
                        7. Verify budget group names match existing budget groups in the system
                        8. Save the returned campaign URL for quick access to campaign management

                        ERROR HANDLING:
                        - Validates all required fields are provided
                        - Checks that referenced ad IDs, offer IDs, and audience names exist
                        - Ensures campaign name uniqueness
                        - Validates date formats and logical date ranges
                        - Verifies at least one channel is configured
                        - Provides detailed error messages for troubleshooting

                        INTEGRATION NOTES:
                        - Supports both simple single-channel and complex multi-channel campaigns
                        - Automatically handles channel-specific configuration requirements
                        - Works in conjunction with ad and offer creation tools for complete campaign setup
                        - Provides comprehensive campaign status and configuration feedback
                        - Always returns the platform URL for immediate campaign access

Arguments

ArgumentTypeNotes
campaign_data object required Complete campaign configuration data

Request

curl
curl -s -X POST https://mcp-server.metadata.io/mcp \
  -H "Authorization: $METADATA_PAT" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"create_campaign","arguments":{"campaign_data":{}}}}'

Response

No recorded response. This tool writes to the account, so it is never executed to build these docs. The request above is still the exact shape to send. Nothing on this page is invented.

Other campaigns tools:

All 160 tools · machine-readable index