Lead to FB CAPI

Cost

GTM container 0$,

nextJS serverless function at Vercel 0$

Meta Conversions API, FB CAPI APP

First we introduce a simple HTML form:

<form id="leadForm">
  <label>
    First Name:
    <input type="text" name="first_name" required>
  </label>
  <br>
  <label>
    Email:
    <input type="email" name="email" required>
  </label>
  <br>
  <button type="submit">Submit</button>
</form>


then a code that collects cookies and form field values and pushes them to the data layer, it also sends the data to a Vercel function with a POST

<script>
document.addEventListener('DOMContentLoaded', function () {
  const form = document.getElementById('leadForm');
  // Use the correct endpoint for your function
  const endpoint = 'https://123-five-gamma.vercel.app/api/fbcapi'; 

  if (form) {
    function getCookie(name) {
      const value = "; " + document.cookie;
      const parts = value.split("; " + name + "=");
      if (parts.length === 2) {
        return parts.pop().split(";").shift();
      }
      return null;
    }

    form.addEventListener('submit', function (e) {
      e.preventDefault();

      const firstName = form.elements.first_name.value;
      const email = form.elements.email.value;
      const fbp = getCookie('_fbp');

      const formData = {
        first_name: firstName,
        email: email,
        fbp: fbp
      };

      // Push data to the data layer for GTM
      window.dataLayer = window.dataLayer || [];
      window.dataLayer.push({
        event: 'formSubmission',
        ...formData
      });

      // Send a POST request to your Vercel function
      fetch(endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(formData)
      })
      .then(response => {
        if (response.ok) {
          console.log('Data sent to Vercel successfully!');
        } else {
          console.error('Failed to send data to Vercel.');
        }
      })
      .catch(error => {
        console.error('Network error:', error);
      });
    });
  }
});
</script>

Vercel function log for the request:


Received data: {
  first_name: 'ffrgtr',
  email: 'ajuj@jdh.com',
  fbp: 'fb.1.1754489633152.84653385640405898'
}

the values are also now available in the data layer for further automation in gtm

However, we go with the vercel way . now the Vercel function has to be send a modified to POST to fb capi (access token and pixel id needed)

the followin updated vercel function has the Fb access token and includes the pixel id, it also normalizes the lead parameters so that they are accepted by FB CAPi



// You will need to install the 'crypto' library to hash data
// npm install crypto

import crypto from 'crypto';

// Replace with your actual values
const FACEBOOK_ACCESS_TOKEN = 'EAAUmJiUQKVgBPFtnfTiI9OQZBIUUUUUUUUOuhGgZBnMZCaR2WxfK8zZCZBVsMV8CiV8gUWeT0PYXt12EqpTlZBpLy7nvC0KXSz51aPRSLZAbkqIGS6iSpUcri3Cf25j8reIlmfvROjtOuRVYRc7Tk'; 
const FACEBOOK_PIXEL_ID = '105100000000076632';

// Function to hash the PII data
function hash(data) {
    if (!data) return null;
    return crypto.createHash('sha256').update(data.trim().toLowerCase()).digest('hex');
}

export async function OPTIONS() {
    return new Response(null, {
        status: 204,
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "POST, OPTIONS",
            "Access-Control-Allow-Headers": "Content-Type",
        },
    });
}

export async function POST(request) {
    const body = await request.json();
    console.log("Received data:", body);

    const { first_name, email, fbp } = body;

    // Build the data payload for Facebook CAPI
    const facebookEventData = {
        data: [{
            event_name: 'Lead', // or 'Purchase', 'CompleteRegistration', etc.
            event_time: Math.floor(Date.now() / 1000), // Current timestamp in seconds
            user_data: {
                fn: hash(first_name),
                em: hash(email),
                fbp: fbp,
                // Add other user data if available (e.g., phone number, last name, city)
            },
            custom_data: {
                // Add any custom properties (e.g., value, currency)
            },
            action_source: 'website',
        }],
    };

    // Send the data to Facebook CAPI
    const fbEndpoint = `https://graph.facebook.com/v20.0/${FACEBOOK_PIXEL_ID}/events?access_token=${FACEBOOK_ACCESS_TOKEN}`;

    try {
        const fbResponse = await fetch(fbEndpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(facebookEventData),
        });

        const fbResponseData = await fbResponse.json();

        if (fbResponse.ok) {
            console.log("Event sent to Facebook successfully:", fbResponseData);
        } else {
            console.error("Failed to send event to Facebook:", fbResponseData);
        }

    } catch (error) {
        console.error("Error sending event to Facebook:", error);
    }

    return new Response(JSON.stringify({ message: 'Data received and processed', data: body }), {
        status: 200,
        headers: { 'Content-Type': 'application/json' },
    });
}

After submitin a Lead, happily Vercel logs confirm lead data collection and confirmation from CAPi event was received at FB:

in the Events Manager there is confirmation a correct Lead was obtained:


the vercel function hashed parameters that needed hashing, now it is just a matter of including more data in the event, as well as the fbc if we want to attribute to a fb ad

Available for hire. If you want me to implement this automation for your business (or if you want a guided demo)

Other Demos

Privacy Policy | Affiliate Disclaimer | Terms & Conditions | Opt-Out Preferences