Skip to main content
Glama

create_meta_campaign

Create a complete Meta (Facebook/Instagram) ad campaign with targeting, creative, and budget in one call. Campaigns are created paused for review before activation.

Instructions

Create a complete Meta (Facebook/Instagram) ad campaign in one call — campaign + ad set with targeting + creative + ad. Created in PAUSED state. Call enable_meta_campaign to activate. Minimum budget $1/day. Requires Starter plan or higher.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesCampaign name. Example: "Spring Sale — Traffic — US"
objectiveNoObjective: OUTCOME_TRAFFIC, OUTCOME_LEADS, OUTCOME_SALES, OUTCOME_ENGAGEMENT, OUTCOME_AWARENESS. Default: OUTCOME_TRAFFIC
daily_budget_usdYesDaily spend limit in USD. Minimum: 1.
destination_urlYesFull URL (including https://) users land on after clicking.
ad_headlineYesBold ad headline. Max 40 characters.
ad_bodyYesMain ad copy. Max 125 characters.
targeting_countriesNoCountry codes. Example: ["US","CA","GB"]. Default: ["US"].
age_minNoMinimum target age. Default: 18.
age_maxNoMaximum target age. Default: 65.

Implementation Reference

  • The handler logic for creating a Meta campaign, which creates the campaign, ad set, creative, and ad in a sequence.
    case 'create_meta_campaign': {
        const denied = licenseCheck('meta');
        if (denied) return fail(denied);
        if (!cfg.hasMeta()) return fail('Meta credentials not set.');
        if (!cfg.metaPage()) return fail('META_PAGE_ID required to create ads.');
        if (!args.name || !args.daily_budget_usd || !args.destination_url || !args.ad_headline || !args.ad_body)
            return fail('Required: name, daily_budget_usd, destination_url, ad_headline, ad_body');
    
        // Validate budget
        const budgetError = validateMetaBudget(args.daily_budget_usd);
        if (budgetError) return fail(budgetError);
    
        // Validate URL
        const urlError = validateUrl(args.destination_url);
        if (urlError) return fail(urlError);
    
        const campaignRes = await metaPost(`/${cfg.metaAccount()}/campaigns`, {
            name: args.name, objective: args.objective || 'OUTCOME_TRAFFIC',
            status: 'PAUSED', special_ad_categories: [],
        });
    
        const adSetRes = await metaPost(`/${cfg.metaAccount()}/adsets`, {
            name: `${args.name} — Ad Set`, campaign_id: campaignRes.id,
            daily_budget: Math.round((args.daily_budget_usd as number) * 100),
            billing_event: 'IMPRESSIONS', optimization_goal: 'LINK_CLICKS',
            targeting: {
                geo_locations: { countries: (args.targeting_countries as string[]) || ['US'] },
                age_min: (args.age_min as number) || 18,
                age_max: (args.age_max as number) || 65,
            },
            status: 'PAUSED',
        });
    
        const creativeRes = await metaPost(`/${cfg.metaAccount()}/adcreatives`, {
            name: `${args.name} — Creative`,
            object_story_spec: {
                page_id: cfg.metaPage(),
                link_data: {
                    message: args.ad_body, link: args.destination_url, name: args.ad_headline,
                    call_to_action: { type: 'LEARN_MORE', value: { link: args.destination_url } },
                },
            },
        });
    
        const adRes = await metaPost(`/${cfg.metaAccount()}/ads`, {
            name: `${args.name} — Ad`, adset_id: adSetRes.id,
            creative: { creative_id: creativeRes.id }, status: 'PAUSED',
        });
    
        return ok({
            success: true, status: 'PAUSED',
            next_step: 'Call enable_meta_campaign with campaign_id to start running.',
            campaign_id: campaignRes.id, adset_id: adSetRes.id,
            creative_id: creativeRes.id, ad_id: adRes.id,
            daily_budget_usd: args.daily_budget_usd,
        });
    }
  • The tool registration and schema definition for 'create_meta_campaign' within the TOOLS array.
        name: 'create_meta_campaign',
        description: 'Create a complete Meta (Facebook/Instagram) ad campaign in one call — campaign + ad set with targeting + creative + ad. Created in PAUSED state. Call enable_meta_campaign to activate. Minimum budget $1/day. Requires Starter plan or higher.',
        inputSchema: {
            type: 'object',
            properties: {
                name:                { type: 'string', description: 'Campaign name. Example: "Spring Sale — Traffic — US"' },
                objective:           { type: 'string', description: 'Objective: OUTCOME_TRAFFIC, OUTCOME_LEADS, OUTCOME_SALES, OUTCOME_ENGAGEMENT, OUTCOME_AWARENESS. Default: OUTCOME_TRAFFIC' },
                daily_budget_usd:    { type: 'number', description: 'Daily spend limit in USD. Minimum: 1.' },
                destination_url:     { type: 'string', description: 'Full URL (including https://) users land on after clicking.' },
                ad_headline:         { type: 'string', description: 'Bold ad headline. Max 40 characters.' },
                ad_body:             { type: 'string', description: 'Main ad copy. Max 125 characters.' },
                targeting_countries: { type: 'array', items: { type: 'string' }, description: 'Country codes. Example: ["US","CA","GB"]. Default: ["US"].' },
                age_min:             { type: 'number', description: 'Minimum target age. Default: 18.' },
                age_max:             { type: 'number', description: 'Maximum target age. Default: 65.' },
            },
            required: ['name', 'daily_budget_usd', 'destination_url', 'ad_headline', 'ad_body'],
        },
    },

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Nolas-Shadow/agent1st-ads-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server