Introduction
In 2026, Meta Ads (formerly Facebook and Instagram Ads) remains the most powerful advertising lever to reach billions of targeted users. With an average ROI of 4:1 for well-optimized campaigns, mastering this platform is essential for marketers and developers. This intermediate tutorial guides you step by step: from manual setup in Ads Manager to automation via Meta's Marketing API.
Why is it crucial? Meta's algorithms are evolving toward predictive AI (Advantage+), making automation essential for scaling. We cover the intuitive interface for quick tests and complete Node.js scripts for production deployments. Imagine deploying 100 ad variations with a single command, using dynamic targeting based on your first-party data. By the end, you'll launch a full campaign that's tracked, optimized, and ready to generate qualified leads.
Prerequisites
- Verified Meta Business Manager account (create one at business.facebook.com).
- Meta Pixel installed on your site (via interface or code).
- Node.js 20+ and npm installed.
- Basic knowledge of JavaScript and HTTP APIs.
- Test budget: €50 minimum per campaign.
- Meta Developers app: create one at developers.facebook.com with
ads_managementpermission.
Install the Meta Business SDK
mkdir meta-ads-api-project
cd meta-ads-api-project
npm init -y
npm install facebook-nodejs-business-sdk dotenv
mkdir src
touch src/index.js .envThis script initializes a dedicated Node.js project and installs the official facebook-nodejs-business-sdk for interacting with the Marketing API. dotenv handles secrets like the access token. Avoid global installs for isolation; run in a dedicated folder to scale to CI/CD.
Get the Access Token and Configure .env
In Meta for Developers, create a 'Business' app and generate a System User Token with scopes ads_management,ads_read. Note down:
- APP_ID
- ACCESS_TOKEN
- AD_ACCOUNT_ID (format: act_123456789)
- PIXEL_ID
Copy into
.env (example below). In Business Manager > Settings > Ad Accounts, verify permissions. Analogy: It's like a Stripe API key – without it, no access to funds (here, ad budgets).Configure Environment Variables
APP_ID=your_app_id_here
ACCESS_TOKEN=EAA...long_lived_token_here
AD_ACCOUNT_ID=act_1234567890
PIXEL_ID=123456789012345
BUSINESS_ID=your_business_id
VERSION=v20.0This .env file stores sensitive credentials. Use a never-expiring token via Graph API Explorer. Common pitfall: short-lived token (1h) that expires in production; always test with curl before scripting. Add .env to .gitignore for security.
Connect and Read the Ad Account
require('dotenv').config();
const AdsPixel = require('facebook-nodejs-business-sdk').AdsPixel;
const BusinessManager = require('facebook-nodejs-business-sdk').BusinessManager;
let ACCESS_TOKEN = process.env.ACCESS_TOKEN;
let APP_ID = process.env.APP_ID;
let AD_ACCOUNT_ID = process.env.AD_ACCOUNT_ID;
let API_VERSION = process.env.VERSION || 'v20.0';
const businessManager = new BusinessManager(APP_ID, ACCESS_TOKEN);
const adAccount = businessManager.getAdAccount(AD_ACCOUNT_ID);
(async () => {
const campaigns = await adAccount.getCampaigns();
console.log('Campagnes existantes:', campaigns.map(c => ({id: c.id(), name: c.name() })));
})();
console.log('Connexion OK à', AD_ACCOUNT_ID);This script tests the connection and lists existing campaigns. It uses BusinessManager for auth. Run with node src/test-connection.js. If error 190 (invalid token), regenerate it. Scalable for health checks in cron jobs.
Create a Campaign via Ads Manager (Complementary Interface)
Alongside the API, use Ads Manager to validate:
- Go to adsmanager.facebook.com.
- Click Create > Campaign.
- Objective: Sales or Traffic.
- Enable Advantage+ Campaign Budget for AI auto-optimization.
Mental screenshot: Daily budget €20, duration 7 days. Copy the generated ID for the API. Why hybrid? Interface for rapid prototyping (5 min), API for bulk (100+ campaigns).
Create a Campaign via API
require('dotenv').config();
const AdAccount = require('facebook-nodejs-business-sdk').AdAccount;
let ACCESS_TOKEN = process.env.ACCESS_TOKEN;
let APP_ID = process.env.APP_ID;
let AD_ACCOUNT_ID = process.env.AD_ACCOUNT_ID;
const adAccount = new AdAccount(AD_ACCOUNT_ID, process.env.ACCESS_TOKEN);
const campaignData = {
name: 'Campagne Test API 2026',
objective: 'CONVERSIONS',
status: 'PAUSED',
special_ad_categories: [],
daily_budget: 2000000, // 20 in cents
};
(async () => {
const campaign = await adAccount.createCampaign([], campaignData);
console.log('Nouvelle campagne ID:', campaign.id());
})();Creates a PAUSED campaign (safe for testing) with conversions objective and €20/day budget. Budget in cents (x100,000 for micro-units). Pitfall: Forgetting PAUSED starts spending immediately. Use this ID for subsequent ad sets.
Create an Ad Set with Targeting
require('dotenv').config();
const Campaign = require('facebook-nodejs-business-sdk').Campaign;
let CAMPAIGN_ID = 'act_1234567890_campaign_id_from_previous'; // Remplacez
let AD_ACCOUNT_ID = process.env.AD_ACCOUNT_ID;
const campaign = new Campaign(CAMPAIGN_ID);
const adsetData = {
name: 'Adset France 25-45 Ans',
optimization_goal: 'CONVERSIONS',
billing_event: 'IMPRESSIONS',
bid_amount: 500, // 5€ max CPC
daily_budget: 1000000, // 10€
status: 'PAUSED',
targeting: {
geo_locations: {countries: ['FR']},
age_min: 25,
age_max: 45,
genders: [2], // 1=Male, 2=Female
},
pixel: [process.env.PIXEL_ID],
};
(async () => {
const adset = await campaign.createAdSet([], adsetData);
console.log('Adset ID:', adset.id());
})();Defines an ad set targeting France, ages 25-45, females, optimized for conversions. geo_locations is a nested object. Budget in cents. Test narrow targeting for ROAS >3. Common error: Missing Pixel ID blocks tracking.
Create a Creative and Ad
require('dotenv').config();
const AdSet = require('facebook-nodejs-business-sdk').AdSet;
let ADSET_ID = 'adset_id_from_previous';
const adSet = new AdSet(ADSET_ID);
const adCreativeData = {
name: 'Creative Test Image',
object_story_spec: {
page_id: 'your_page_id',
link_data: {
call_to_action: {type: 'SHOP_NOW', value: {link: 'https://your-site.com'}},
link: 'https://your-site.com',
message: 'Découvrez nos offres exclusives ! 🔥',
image_hash: 'your_image_hash_from_upload',
},
},
};
const adData = {
name: 'Ad Test 2026',
adset_id: ADSET_ID,
creative: {creative_id: 'creative_id_from_previous'},
status: 'PAUSED',
};
(async () => {
const creative = await adSet.createAdCreative([], adCreativeData);
console.log('Creative ID:', creative.id());
// Puis créez l'ad avec creative.id()
// const ad = await adSet.createAd([], adData);
})();Creates a creative with image hash (upload via API or interface first) and CTA link. object_story_spec for dynamic formats. Activate with PUBLISH. Pitfall: Invalid image hash (use /act_
Launch and Monitor the Campaign
In Ads Manager, edit the IDs and switch from PAUSED to PUBLISH. Monitor Events Manager for pixel data. Use API for insights: adset.read(['impressions', 'clicks']). Tip: Enable Advantage+ Placements for AI auto-optimization.
Best Practices
- Systematic A/B testing: 3-5 creatives per ad set, split budget 50/50.
- Pixel retargeting: Create custom audiences (7-day visitors) for 2x ROAS.
- CBO budgets: Campaign Budget Optimization lets Meta's AI allocate dynamically.
- GDPR compliance: Add consent banner, avoid sensitive data.
- Scaling: Double budget if CPA below threshold after 50 conversions.
Common Errors to Avoid
- Expired token: Always use never-expiring System User Tokens.
- Wrong budget units: Forgetting cents = 100x overspend.
- Too broad targeting: >10M audience = waste; aim for 1-5M.
- No pixel: Zero tracking = no optimization.
Next Steps
Master Advantage+ AI and lookalike audiences. Check the official Marketing API docs. For expert training, explore our Learni Growth Marketing courses.