Header Ads

ads header

Complete Tutorial: Meta Conversions API with Cloudflare Pages





Meta Conversions API + Cloudflare Pages: Complete Setup Guide | HireLancer
📡 Step-by-Step Tutorial

Meta Conversions API with Cloudflare Pages

Set up server-side conversion tracking in 6 steps — no backend server needed, fully free to host.

🧑‍💻 By Somit · HireLancer ⏱ 20 min setup 🆓 Free hosting 🔒 Privacy-compliant
💡
What & Why The Meta Conversions API (CAPI) sends conversion events directly from your server to Meta — bypassing ad blockers and iOS tracking restrictions. This gives you more accurate data than the browser-only Pixel alone.
1

Create Backend Function in GitHub

This function runs on Cloudflare's edge — no server needed.

Navigate to your GitHub repository
  • Open your GitHub repository (e.g. TurboNifyIQ)
  • Click "Add file""Create new file"
Create the function file

Name the file exactly as shown below — the path matters for Cloudflare Pages routing:

File Path
functions/api/track.js

Then paste this complete code into the file:

JavaScript · functions/api/track.js
// Meta Conversions API Backend Function for Cloudflare Pages

export async function onRequestPost(context) {
  const { request, env } = context;
  
  try {
    // Get conversion data from frontend
    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);
    
    // Build the Meta CAPI payload
    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
    };
    
    // Send to Meta Conversions API
    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',
        'Access-Control-Allow-Headers': 'Content-Type'
      }
    });
    
  } catch (error) {
    return new Response(JSON.stringify({ success: false, error: error.message }), {
      status: 500,
      headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }
    });
  }
}

// Handle preflight CORS requests
export async function onRequestOptions() {
  return new Response(null, {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'POST, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type'
    }
  });
}

// 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('');
}
Commit the file
  • Set commit message: Add Meta Conversions API backend function
  • Click "Commit new file"

2

Configure Environment Variables in Cloudflare Pages

Store your secret keys safely — never hardcode them in your files.

Navigate to Cloudflare Pages Settings
  • Go to Cloudflare DashboardPages
  • Click your project name → SettingsEnvironment Variables
Add both environment variables
Variable Name Value Type
META_ACCESS_TOKEN Your access token (starts with EAA...) SECRET
META_PIXEL_ID Your Pixel ID (e.g. 521450497014626) TEXT
⚠️
Important Set variables for both Production and Preview environments if you want tracking to work in preview deployments too.
Deploy changes

Click "Save and deploy" and wait 1–2 minutes for the deployment to complete.


3

Add Frontend Code to Your HTML File

This code fires conversion events from the browser to your backend function.

Edit your index.html in GitHub
  • Open index.html in your repository
  • Click the ✏️ pencil icon to edit
  • Find the closing </body> tag
  • Paste the code below right before </body>
JavaScript · Paste before </body>
/* ===== Meta Conversions API – Frontend ===== */

// Core function: sends an event to your /api/track backend
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:', result);
    return result;
  } catch (error) {
    console.error('Meta conversion error:', error);
  }
}

// 1. Auto-track page view on load
window.addEventListener('load', () => sendMetaConversion('PageView'));

// 2. Auto-track form submissions and CTA button clicks
document.addEventListener('DOMContentLoaded', function() {
  
  // Track form submissions
  document.querySelectorAll('form').forEach(form => {
    form.addEventListener('submit', function() {
      const emailInput = form.querySelector('input[type="email"]');
      sendMetaConversion('Lead', emailInput?.value);
    });
  });

  // Track CTA button clicks — add your own class names here
  document.querySelectorAll('.cta-button, .download-btn, .signup-btn').forEach(btn => {
    btn.addEventListener('click', () => sendMetaConversion('ViewContent'));
  });
  
});

// 3. Helper functions – call these anywhere in your code
function trackPurchase(email, value, currency = 'USD') {
  sendMetaConversion('Purchase', email, value, currency);
}
function trackLead(email)    { sendMetaConversion('Lead', email); }
function trackSignup(email)   { sendMetaConversion('CompleteRegistration', email); }
function trackDownload()       { sendMetaConversion('ViewContent'); }
Commit your changes

Commit message: Add Meta Conversions API frontend code


4

Test the Integration

Make sure everything is firing correctly before going live.

Wait for deployment then test
  • Wait 2–3 minutes for Cloudflare Pages to deploy
  • Open your live website
  • Press F12 → go to the Console tab
  • Refresh the page — you should see a success message
Success looks like this in your console Meta conversion: {success: true, eventId: "1718xxx...", metaResponse: {…}}
Run manual tests from the console
Browser Console Tests
// Test a page view
sendMetaConversion('PageView');

// Test a lead with email
sendMetaConversion('Lead', '[email protected]');

// Test a purchase event
trackPurchase('[email protected]', 99.99, 'USD');

5

Verify in Meta Events Manager

Confirm that Meta is receiving your events on their end.

Check Events Manager
  • Go to Meta Business ManagerEvents Manager
  • Select your Pixel → click the Test Events tab
  • Your events should appear within a few seconds of firing them
Standard Meta event types
Event Name
When to Use
PageView
Someone visits any page
Lead
Form submitted, inquiry sent
Purchase
Completed a transaction
CompleteRegistration
Account signup completed
ViewContent
Viewed key content or product
AddToCart
Item added to shopping cart

6

Troubleshooting Common Issues

If something isn't working, check these things first.

ProblemFix
No events showing in Events Manager Check browser console for JavaScript errors
403 Forbidden error Your META_ACCESS_TOKEN is invalid or expired
Invalid Pixel ID error Double-check your META_PIXEL_ID value in Cloudflare
CORS errors in console Make sure the backend function includes the CORS headers (already in the code above)
Function not found (404) Confirm the file is at functions/api/track.js — path must match exactly
Quick debug checklist
  • Browser console shows {success: true}
  • Events appearing in Meta Events Manager
  • No red errors in browser console
  • API endpoint returns 200 status codes
  • Environment variables saved and deployment completed

+

Bonus: Custom Event Examples

Copy-paste ready snippets for advanced tracking scenarios.

Track scroll depth (75%)
JavaScript
let scrollTracked = false;
window.addEventListener('scroll', function() {
  const pct = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100;
  if (pct > 75 && !scrollTracked) {
    scrollTracked = true; // fire once only
    sendMetaConversion('ViewContent');
  }
});
Advanced form tracking with event type detection
JavaScript
document.querySelectorAll('form').forEach(form => {
  form.addEventListener('submit', function() {
    const email = new FormData(form).get('email');
    
    // Detect form type by CSS class
    let event = 'Lead';
    if (form.classList.contains('signup-form'))   event = 'CompleteRegistration';
    if (form.classList.contains('purchase-form')) event = 'Purchase';
    
    sendMetaConversion(event, email);
  });
});

No comments

Powered by Blogger.