Implementation

This document explains how to implement Embedded Signup and capture the data it generates to onboard business customers onto the WhatsApp Business Platform.

Before You Start

  • You must already be a Solution Partner or Tech Provider (i.e, have completed the steps in our Become a Solution Partner or Become a Tech Provider documents).
  • If your business customers will be using your app to send and receive messages, you should already know how to use the API to send and receive messages using your own WhatsApp Business Account and business phone numbers, know how create and manage templates, and have a webhooks callback endpoint properly set up to digest webhooks.
  • You must be subscribed to the account_update webhook, as this webhook is triggered whenever a customer successfuly completes the Embedded Signup flow and contains business information you will need.
  • If you are a Solution Partner, you must already have a line of credit.
  • The server where you will be hosting Embedded Signup must have a valid SSL certificate.

Step 1: Add allowed domains

Load your app in the App Dashboard and navigate to Facebook Login for Business > Settings > Client OAuth settings:

Set the following toggles to Yes:

  • Client OAuth login
  • Web OAuth login
  • Enforce HTTPS
  • Embedded Browser OAuth Login
  • use Strict Mode for redirect URIs
  • Login with the JavaScript SDK

Embedded Signup relies on the JavaScript SDK. When a business customer completes the Embedded Signup flow, the customer's WABA ID, business phone number ID, and an exchangeable token code will be returned to the window that spawned the flow, but only if the domain of the page that spawned the flow is listed in the Allowed domains and Valid OAuth redirect URIs fields.

Add any domains where you plan on hosting Embedded Signup, including any development domains where you will be testing the flow, to these fields. Only domains that have enabled https are supported.

Step 2: Create a Facebook Login for Business configuration

A Facebook Login for Business configuration defines which permissions to request, and what additional information to collect, from business customers who access Embedded Signup.

Navigate to Facebook Login for Business > Configurations and click the + Create configuration button to access the configuration flow.

Use a name that will help you differentiate this configuration from any others you may create in the future. When completing the flow, be sure to select the WhatsApp Embedded Signup login variation:

When choosing assets and permissions, select only those assets and permissions that you will actually need from your business customers.

For example, if you select the Catalogs asset but don't actually need access to customer catalogs, your customers will likely abandon the flow at the catalog selection screen and ask you for clarification.

When you complete the configuration flow, capture your configuration ID, as you will need it in the next step.

Step 3: Add Embedded Signup to your website

Add the following HTML and JavaScript code to your website. This is the complete code needed to implement Embedded Signup. Each portion of the code will be explained in detail below.

<!-- SDK loading -->
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js"></script>

<script>
  // SDK initialization
  window.fbAsyncInit = function() {
    FB.init({
      appId: '<APP_ID>', // your app ID goes here
      autoLogAppEvents: true,
      xfbml: true,
      version: '<GRAPH_API_VERSION>' // Graph API version goes here
    });
  };
  
  // Session logging message event listener
  window.addEventListener('message', (event) => {
    if (event.origin !== "https://www.facebook.com" && event.origin !== "https://web.facebook.com") return;
    try {
      const data = JSON.parse(event.data);
      if (data.type === 'WA_EMBEDDED_SIGNUP') {
        console.log('message event: ', data); // remove after testing
        // your code goes here
      }
    } catch {
      console.log('message event: ', event.data); // remove after testing
      // your code goes here
    }
  });
  
  // Response callback
  const fbLoginCallback = (response) => {
    if (response.authResponse) {
      const code = response.authResponse.code;
      console.log('response: ', code); // remove after testing
      // your code goes here
    } else {
      console.log('response: ', response); // remove after testing
      // your code goes here
    }
  }
  
  // Launch method and callback registration
  const launchWhatsAppSignup = () => {
    FB.login(fbLoginCallback, {
      config_id: '<CONFIGURATION_ID>', // your configuration ID goes here
      response_type: 'code',
      override_default_response_type: true,
      extras: {
        setup: {},
        featureType: '',
        sessionInfoVersion: '3',
      }
    });
  }
</script>

<!-- Launch button  -->
<button onclick="launchWhatsAppSignup()" style="background-color: #1877f2; border: 0; border-radius: 4px; color: #fff; cursor: pointer; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-weight: bold; height: 40px; padding: 0 24px;">Login with Facebook</button>

SDK Loading

This portion of the code loads the Facebook JavaScript SDK asynchronously:

<!-- SDK loading -->
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js"></script>

SDK Initialization

This portion of the code initializes the SDK. Add your app ID and the latest Graph API version here.

// SDK initialization
window.fbAsyncInit = function() {
  FB.init({
    appId: '<APP_ID>', // your app ID goes here
    autoLogAppEvents: true,
    xfbml: true,
    version: '<GRAPH_API_VERSION>' // Graph API version here
  });
};

Replace the following placeholders with your own values.

Placeholder Description Example value

<APP_ID>

Required.

Your app ID. This is displayed at the top of the App Dashboard.

21202248997039

<GRAPH_API_VERSION>

Required.

Graph API version. This indicates which version of Graph API to call, if you are relying on the SDK's methods to perform API calls.

In the context of Embedded Signup, you won't be relying on the SDK's methods to perform API calls, so we recommend that you just set this to the latest API version:

v21.0
v21.0

Session logging message event listener

This portion of the code creates a message event listener that captures the business customer's newly generated business phone number ID and WABA ID (if they successfully completed the flow) or the name of the screen they abandoned (if they abandoned the flow).

// Session logging message event listener
window.addEventListener('message', (event) => {
  if (event.origin !== "https://www.facebook.com" && event.origin !== "https://web.facebook.com") return;
  try {
    const data = JSON.parse(event.data);
    if (data.type === 'WA_EMBEDDED_SIGNUP') {
      console.log('message event: ', data); // remove after testing
      // your code goes here
    }
  } catch {
    console.log('message event: ', event.data); // remove after testing
    // your code goes here
  }
});

When a business customer successfully completes or abandons the flow, a message event and object will be sent to the window that spawned the flow. This object will get assigned to the data constant.

Add your own custom code to the try-catch statement that can send this object to your server.

This object will have one of two structures, based on if the customer completed or abandoned the flow.

Successful flow completion structure:

{
  data: {
    phone_number_id: "<CUSTOMER_BUSINESS_PHONE_NUMBER_ID>",
    waba_id: "<CUSTOMER_WABA_ID>"
  },
  type: "WA_EMBEDDED_SIGNUP",
  event: "FINISH",
  version: 3
}

Abandoned flow structure:

{
  data: {
    current_step: "<CURRENT_STEP>",
  },
  type: "WA_EMBEDDED_SIGNUP",
  event: "CANCEL",
  version: 3
}

Parse this object on your server to extract and capture the customer's phone number ID and WABA ID, or to determine which screen they abandoned. See Abandoned flow screens for a list of possible <CURRENT_STEP> values and the screens they correspond to.

Note that the try-catch statement in the code above has two statements that can be used for testing purposes:

console.log('message event: ', data); // remove after testing

console.log('message event: ', event.data); // remove after testing

These statements just dump the returned phone number and WABA IDs, or the abandoned screen string, to the JavaScript console. You can leave this code in place and keep the console open to easily see what gets returned when you are testing the flow, but you should remove them when you are done testing.

Response callback

Whenever a business customer successfully completes the Embedded Signup flow, we will send an exchangeable token code in a JavaScript response to the window that spawned the flow.

// Response callback
const fbLoginCallback = (response) => {
  if (response.authResponse) {
    const code = response.authResponse.code;
    console.log('response: ', code); // remove after testing
    // your code goes here
  } else {
    console.log('response: ', response); // remove after testing
    // your code goes here
  }
}

The callback function assigns the exchangeable token code to a code constant.

Add your own, custom code to the if-else statement that sends this code to your server so you can later exchange it for the customer's business token when you onboard the business customer.

The exchangeable token code has a time-to-live of 30 seconds, so make sure you are able to exchange it for the customer's business token before the code expires. If you are testing and just dumping the response to your JavaScript console, then manually exchanging the code using another app like Postman or your terminal with cURL, we recommend that you set up your token exchange query before you begin testing.

Note that the if-else statement in the code above has two statements that can be used for testing purposes:

console.log('response: ', code); // remove after testing

console.log('response: ', response); // remove after testing

These statements just dump the code or the raw response to the JavaScript console. You can leave this code in place and keep the console open to easily see what gets returned when you are testing the flow, but you should remove them when you are done testing.

Launch method and callback registration

This portion of the code defines a method which can be called by an onclick event that registers the response callback from the previous step and launches the Embedded Signup flow.

Add your configuration ID here.

// Launch method and callback registration
const launchWhatsAppSignup = () => {
  FB.login(fbLoginCallback, {
    config_id: '<CONFIGURATION_ID>', // your configuration ID goes here
    response_type: 'code',
    override_default_response_type: true,
    extras: {
      setup: {},
      featureType: '',
      sessionInfoVersion: '3',
    }
  });
}

Launch button

This portion of the code defines a button that calls the launch method from the previous step when clicked by the business customer.

<!-- Launch button -->
<button onclick="launchWhatsAppSignup()" style="background-color: #1877f2; border: 0; border-radius: 4px; color: #fff; cursor: pointer; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-weight: bold; height: 40px; padding: 0 24px;">Login with Facebook</button>

Testing

Once you have completed all of the implementation steps above, you should be able to test the flow by simulating a business customer while using your own Meta credentials. Anyone who you have added as an admin or developer on your app (in the App Dashboard > App roles > Roles panel) can also begin testing the flow, using their own Meta credentials.

Onboarding Business Customers

Embedded Signup generates assets for your business customers, and grants your app access to those assets. However, you still must perform a series of API calls to fully onboard new business customers who have completed the flow.

The API calls you must make to onboard customers are different for Solution Partners and Tech Providers/Tech Partners.