create_demandgen_campaign

Google Ads Write

๐Ÿšจ **IF THIS TOOL RETURNS A QUOTA ERROR:** - The error message will include a clickable upgrade link - Show the FULL error message to the user (it contains the upgrade link) - DO NOT attempt to work ar

Endpoint

POST https://api.adspirer.ai/api/v1/tools/create_demandgen_campaign/execute

Headers

Description

๐Ÿšจ **IF THIS TOOL RETURNS A QUOTA ERROR:** - The error message will include a clickable upgrade link - Show the FULL error message to the user (it contains the upgrade link) - DO NOT attempt to work around the error or use alternative data - DO NOT create campaigns or perform actions without valid tool data - STOP and direct the user to upgrade via the provided link ๐Ÿ”„ LONG-RUNNING TOOL: Creates a Demand Gen campaign across ALL Google channels โ€” YouTube, Discover, Gmail, Display, and Maps. Emits MCP progress updates during creation (typically 10-20 seconds). โš ๏ธ CRITICAL WARNING โš ๏ธ - Call this tool ONLY ONCE per campaign - Creates REAL campaigns that cost REAL money - Do NOT retry automatically if errors occur - Report errors to user instead of retrying ๐ŸŒ **Demand Gen Campaign Channels (ALL enabled by default):** โœ… YouTube In-Feed (search results & related videos) โœ… YouTube In-Stream (before/during/after videos) โœ… YouTube Shorts (Shorts feed) โœ… Gmail (Promotions & Social tabs) โœ… Discover (Google Discover feed) โœ… Display (Google Display Network) โŒ Maps (opt-in, disabled by default) ๐Ÿ“‹ **YOUR CRITICAL ROLE: Campaign Strategist & Text Creator** **STEP 1: Collect Campaign Details from User** YOU MUST collect these from the user: 1. **Campaign Name** - Descriptive and unique 2. **Daily Budget** - In account's native currency (recommended $20+/day) 3. **Ad Format** - multi_asset (images) or video_responsive (videos) 4. **Final URL** - Landing page 5. **Business Name** - Max 25 characters **STEP 2: Discover Existing Assets** ๐Ÿ”ด MANDATORY: Call discover_existing_assets to find existing logos/images. - If logos found โ†’ use logo_asset_id or existing_images.logos_square - If NO logos โ†’ ask user for logo URL, run validate_and_prepare_assets **STEP 3: Generate Ad Copy** - Headlines (1-5): STRICT 40 character max each - Descriptions (1-5): STRICT 90 character max each - Long Headlines (optional, for video_responsive): 90 char max each **STEP 4: Prepare Images/Videos** For multi_asset: Need landscape (1.91:1) OR square (1:1) marketing images + logo For video_responsive: Need YouTube video IDs (validate first) + logo **STEP 5: Call create_demandgen_campaign with complete payload** **Bidding Options (your choice is honored โ€” engine is advisory only):** - MAXIMIZE_CLICKS: Default, works without conversion tracking - MAXIMIZE_CONVERSIONS: Requires conversion tracking - TARGET_CPA: Requires target_cpa value - MAXIMIZE_CONVERSION_VALUE: Requires conversion tracking - TARGET_ROAS: Requires target_roas value **Channel Controls (optional):** Pass channels dict to disable specific channels: {"gmail": false, "display": false} โ†’ YouTube + Discover only **STEP 6: MANDATORY โ€” Add Extensions After Creation** After success, add sitelinks, callouts, and structured snippets. **Execution Time:** 10-20 seconds **CRITICAL REMINDERS:** - Campaign starts PAUSED for user safety - This costs real money โ€” be transparent - Never retry on failure โ€” report error to user

Request body

All tool arguments are wrapped in an arguments object.

FieldTypeDescription
campaign_namestring requiredCampaign name (e.g., 'DemandGen Summer Promo 2026')
budget_dailynumber requiredDaily budget in the account's native currency. IMPORTANT: Do NOT convert currencies โ€” pass the user's amount as-is. Example: if user says 'โ‚น1000/day', pass 1000 (not a USD conversion). Google recommends minimum ~$20/day USD equivalent for Demand Gen campaigns.
ad_formatstring optionalAd format: 'multi_asset' (image ads, default), 'video_responsive' (video ads). multi_asset requires marketing images. video_responsive requires YouTube video IDs. default: "multi_asset"
final_urlstring requiredLanding page URL (must match verified domain). Example: 'https://example.com/product'
business_namestring requiredBusiness name, max 25 characters. Example: 'Adspirer'
headlinesarray requiredMUST BE JSON ARRAY: 1-5 headlines, each EXACTLY 40 characters maximum. Example: ["AI Ad Management", "Skip the Dashboard"]. COUNT CHARACTERS! ANY over 40 will be REJECTED!
descriptionsarray requiredMUST BE JSON ARRAY: 1-5 descriptions, each EXACTLY 90 characters maximum. Example: ["Manage ads with AI - no dashboard needed."]. COUNT CHARACTERS BEFORE CALLING!
long_headlinesarray optionalMUST BE JSON ARRAY: Optional 1-5 long headlines, max 90 characters each. Required for video_responsive format. Falls back to headlines if not provided.
call_to_actionstring optionalCall-to-action label. Options: LEARN_MORE, SHOP_NOW, SIGN_UP, SUBSCRIBE, DOWNLOAD, BOOK_NOW, CONTACT_US, GET_QUOTE, APPLY_NOW
target_locationsarray optionalGeographic targets globally (e.g., ['India', 'United States', 'London']). Supports countries, states, cities worldwide. Defaults to United States.
target_languagesarray optionalLanguage targets as ISO codes (e.g., ['en', 'es']). Defaults to English.
bidding_strategystring optionalBidding strategy: MAXIMIZE_CLICKS (default), MAXIMIZE_CONVERSIONS, TARGET_CPA, MAXIMIZE_CONVERSION_VALUE, TARGET_ROAS. Your explicit choice is honored โ€” the engine is advisory only. default: "MAXIMIZE_CLICKS"
target_cpanumber optionalTarget CPA in account's native currency (only for TARGET_CPA bidding). Example: 25.0
target_roasnumber optionalTarget ROAS multiplier (only for TARGET_ROAS bidding). Example: 3.5 means 350% return on ad spend.
channelsobject optionalOptional channel controls. Keys: youtube_in_feed, youtube_in_stream, youtube_shorts, gmail, discover, display. All default to true (full reach). Example: {"gmail": false, "display": false} to exclude those channels.
marketing_imagesarray optionalLandscape images (1.91:1) as [{"url": "https://...", "name": "img1"}]. At least landscape OR square images required for multi_asset.
square_marketing_imagesarray optionalSquare images (1:1) as [{"url": "https://...", "name": "img1"}].
portrait_marketing_imagesarray optionalPortrait images (4:5) as [{"url": "https://...", "name": "img1"}]. Optional.
existing_imagesobject optionalExisting image asset resource names to reuse (from discover_existing_assets). Keys: marketing_images_landscape, marketing_images_square, marketing_images_portrait, logos_square. Example: {"marketing_images_landscape": ["customers/123/assets/456"]}
youtube_video_idsarray optionalYouTube video IDs (each 11 chars) for video_responsive format. 1-5 videos. Must be validated first using validate_video tool.
logo_asset_idstring optionalLogo image asset ID from discover_existing_assets.
logo_imagesarray optionalNew logo images as [{"url": "https://...", "name": "logo1"}].
asset_bundle_idstring optionalAsset bundle ID (UUID) from validate_and_prepare_assets.
audience_segmentsobject optionalOptional: Audience targeting for the campaign. CRITICAL: Only use segment IDs returned by search_audiences tool. NEVER fabricate or guess IDs -- wrong IDs target unrelated audiences and waste budget. If search_audiences returns no results, skip audience_segments entirely. Keys: 'in_market_audience_ids' (List[int] -- people actively researching), 'affinity_audience_ids' (List[int] -- people with long-term interests), 'custom_audience_ids' (List[str] -- custom audience resource names from search_audiences), 'user_list_ids' (List[str] -- remarketing/customer match resource names). Example: {'in_market_audience_ids': [80463, 80520], 'affinity_audience_ids': [92913]}
customer_idstring optionalGoogle Ads customer ID. Required for multi-account users. Get from list_connected_accounts.

Example request

{
  "arguments": {
    "campaign_name": "string",
    "budget_daily": 1.0,
    "final_url": "https://example.com",
    "business_name": "string",
    "headlines": [
      "string"
    ],
    "descriptions": [
      "string"
    ],
    "ad_format": "multi_asset",
    "long_headlines": [
      "string"
    ],
    "call_to_action": "string",
    "target_locations": [
      "string"
    ],
    "target_languages": [
      "string"
    ],
    "bidding_strategy": "MAXIMIZE_CLICKS"
  }
}

Example responses

200 โ€” Success

{
  "success": true,
  "data": {
    "text": "(tool-specific textual output for create_demandgen_campaign)",
    "quota": {
      "used": 42,
      "limit": 150,
      "tier": "plus",
      "period_end": "2026-05-01"
    }
  },
  "tool": "create_demandgen_campaign"
}

400 โ€” Tool-level error (bad arguments / multi-account selection)

{
  "success": false,
  "error": "You have 25 meta_ads accounts connected. Please specify which account to use by passing the ad_account_id parameter:\n  - Acme Holdings (ad_account_id=\"act_123456789\")\n  - Acme EU (ad_account_id=\"act_987654321\")",
  "is_error": true,
  "tool": "create_demandgen_campaign"
}

402 โ€” Quota exhausted

{
  "success": false,
  "error": "\ud83d\udea8 Monthly limit reached (150/150 tool calls on Plus tier).\nUpgrade to Pro at https://adspirer.ai to keep building.",
  "is_error": true,
  "tool": "create_demandgen_campaign",
  "quota": {
    "used": 150,
    "limit": 150,
    "tier": "plus",
    "period_end": "2026-05-01",
    "upgrade_url": "https://adspirer.ai"
  }
}

Try it live


Adspirer REST API โ€” get an API key at adspirer.ai/keys ยท adspirer.ai