The Meta Conversions API (CAPI) is no longer "optional." With ad blockers and iOS tracking restrictions cutting into browser-based Pixel data, CAPI sends events directly from your server to Meta.
The best part? You can set this up for free using Cloudflare Pages and GitHub—no dedicated backend server required.
📋 What We’ll Cover
Create the backend function in GitHub
Set environment variables in Cloudflare Pages
Add the frontend tracking code to your HTML
Test the integration
Verify events in Meta Events Manager
Troubleshoot common issues
1. Create the Backend Function in GitHub
We’ll use Cloudflare Functions to run a small piece of JavaScript on the edge.
Open your GitHub repository.
Create a new file at exactly this path:
functions/api/track.jsPaste the following code:
// Meta Conversions API Backend Function for Cloudflare Pages
export async function onRequestPost(context) {
const { request, env } = context;
try {
const data = await request.json();
const { eventName, email, value, currency = 'USD' } = data;
// Generate unique event ID
const eventId = Date.now().toString() + Math.random().toString(36).substr(2, 9);
const conversionData = {
data: [{
event_name: eventName,
event_time: Math.floor(Date.now() / 1000),
event_id: eventId,
action_source: 'website',
event_source_url: request.headers.get('referer') || 'https://your-domain.com',
user_data: {
em: email ? await hashEmail(email) : null,
client_ip_address: request.headers.get('CF-Connecting-IP'),
client_user_agent: request.headers.get('User-Agent')
},
custom_data: {
currency: currency,
value: value ? parseFloat(value) : null
}
}],
access_token: env.META_ACCESS_TOKEN
};
const response = await fetch(
`https://graph.facebook.com/v18.0/${env.META_PIXEL_ID}/events`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(conversionData)
}
);
const result = await response.json();
return new Response(JSON.stringify({ success: true, eventId, metaResponse: result }), {
status: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS'
}
});
} catch (error) {
return new Response(JSON.stringify({ success: false, error: error.message }), { status: 500 });
}
}
// SHA-256 hash email for privacy compliance
async function hashEmail(email) {
const encoder = new TextEncoder();
const data = encoder.encode(email.toLowerCase().trim());
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
2. Configure Environment Variables
Never hardcode your API keys. Store them safely in the Cloudflare Dashboard.
Go to Cloudflare Dash → Pages → [Your Project] → Settings.
Under Environment Variables, add:
META_ACCESS_TOKEN: Your secret token from Meta Events Manager.META_PIXEL_ID: Your 15-digit Pixel ID.
Click Save and Deploy.
3. Add Frontend Tracking Code
This code triggers the event from your user's browser to your new /api/track endpoint.
Paste this script right before your closing </body> tag in index.html:
async function sendMetaConversion(eventName, email = null, value = null, currency = 'USD') {
try {
const response = await fetch('/api/track', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ eventName, email, value, currency })
});
const result = await response.json();
console.log('Meta conversion status:', result);
} catch (error) {
console.error('CAPI Error:', error);
}
}
// Auto-track PageView
window.addEventListener('load', () => sendMetaConversion('PageView'));
4. Test the Integration
Once deployed, open your site and your browser's console (F12).
Refresh the page.
You should see:
{success: true, eventId: "..."}.If you see a 404, your function file is in the wrong folder. It must be in
/functions/api/.
5. Verify in Meta Events Manager
Go to Events Manager → Data Sources.
Select your Pixel and click the Test Events tab.
Enter your website URL.
You should see events appearing with the "Connection Method" labeled as Server.
| Event Name | Use Case |
PageView | Standard page visit |
Lead | Form submission/Inquiry |
Purchase | Successful transaction |
AddToCart | Product added to cart |
6. Troubleshooting
403 Forbidden: Your Access Token is wrong or expired.
CORS Error: Ensure the
onRequestOptions(preflight) function is included if you are calling the API from a different subdomain.No Events: Check if an ad-blocker is blocking the frontend fetch call to your own API (rare, but possible).
🚀 Bonus: Track Scroll Depth
Want to know if users actually read your content? Add this:
let scrollTracked = false;
window.addEventListener('scroll', () => {
const pct = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100;
if (pct > 75 && !scrollTracked) {
scrollTracked = true;
sendMetaConversion('ViewContent');
}
});
