Create Lead Forms and Ads

This page describes how you can create and manage Lead Forms and how to create Lead Ads through the API. Before you can create a Lead Form, you need to create a Legal Content and Context Card (optional). Note: You must use a page access token for this API.

Create a Legal Content that is usable across all your forms. This returns a legal_content_id you need to provide when creating a form. You can also retrieve all Legal Content IDs created for a page by making a GET call to {PAGE_ID}/leadgen_legal_contents.

This code sample shows how to create Legal Content; see reference docs for field details.

use FacebookAds\Api;
use FacebookAds\Http\RequestInterface;

$params = array(
  'privacy_policy' => array(
    'url' => '<URL>',
    'link_text' => 'Privacy Policy'
  ),
  'custom_disclaimer' => array(
    'title' => 'Terms and Conditions',
    'body' => array(
      'text' => 'My custom disclaimer',
      'url_entities' => array(
        array("offset" => 3, "length" => 6, "url" => '<URL>')
      ),
    ),
    'checkboxes' => array(array(
      "is_required" => false,
      "is_checked_by_default" => false,
      "text" => "Allow to contact you",
      "key" => "checkbox_1",
    ))
  ),
);

$data = Api::instance()->call(
  '/'.<PAGE_ID>.'/leadgen_legal_content',
  RequestInterface::METHOD_POST,
  $params)->getContent();
curl \
  -F 'privacy_policy={"url":"<URL>","link_text":"Privacy Policy"}' \
  -F 'custom_disclaimer={ 
    "title": "Terms and Conditions", 
    "body": { 
      "text": "My custom disclaimer", 
      "url_entities": [ 
        { 
          "offset": 3, 
          "length": 6, 
          "url": "<URL>" 
        } 
      ] 
    }, 
    "checkboxes": [ 
      { 
        "is_required": false, 
        "is_checked_by_default": false, 
        "text": "Allow to contact you", 
        "key": "checkbox_1" 
      } 
    ] 
  }' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_legal_content

Create a Context Card

Create a Context Card you can use when creating a form. This returns a context_card_id, which you can use when creating a form. You can also retrieve all the Context Card IDs created for a page by making a GET call to {PAGE_ID}/leadgen_context_cards. See Context Card Reference.

This code sample shows how to create Context Card; see reference docs for field details.

use FacebookAds\Api;
use FacebookAds\Http\RequestInterface;

$params = array(
  'title' => 'title',
  'style' => 'LIST_STYLE',
  'content' => array(
    'Easy sign-up flow',
    'Submit your info to have a chance to win',
  ),
  'button_text' => 'Get started',
);

$data = Api::instance()->call(
  '/'.<PAGE_ID>.'/leadgen_context_cards',
  RequestInterface::METHOD_POST,
  $params)->getContent();
curl \
  -F 'title=title' \
  -F 'style=LIST_STYLE' \
  -F 'content=["Easy sign-up flow","Submit your info to have a chance to win"]' \
  -F 'button_text=Get started' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_context_cards

Create a Thank You Card

Using this field, you can edit or customize the thank you page. Many of the fields for this feature are optional in API, except you must provide a website URL and a default value. To create a new thank you page, make a POST to PAGE_ID/leadgen_thank_you_page. For example:

curl -i -X POST \
 -d "title=custom_title" \
 -d "body=This is custom thank you page" \
 -d "button_type=VIEW_WEBSITE" \
 -d "button_text=View this website" \
 -d "website_url=www.anadvertiser.com" \
 -d "access_token=TOKEN" \
 "https://graph.facebook.com/API_VERSION/PAGE_ID/leadgen_thank_you_page"

On success, Facebook returns the ID of your new thank you page. Options include:

  • body - Body of the thank you page
  • business_phone_number - Phone number with full international number
  • button_text - Text shown on the call-to-action (CTA) button of static footer
  • button_type - This must be of type {'VIEW_WEBSITE', "DOWNLOAD"}
  • country_code - Two-letter ISO country code that represents a specified country
  • enable_messenger - Determines whether to allow users to message business
  • title - Title of the thank you page
  • website_url - URL of website where Facebook redirects someone when they click the CTA button

Create a Lead Form

Create a Lead Form with questions you can display in Lead Ads; see Lead Form, Reference. Note: You can use this API to also create a form by directly passing the parameters for Legal Content and Context Card.

use FacebookAds\Object\Fields\LeadgenFormFields;
use FacebookAds\Object\Fields\LeadgenQuestionFields;
use FacebookAds\Object\LeadgenForm;
use FacebookAds\Object\LeadGenQuestion;

$form = new LeadgenForm(null, <PAGE_ID>);
$form->setData(array(
  LeadgenFormFields::NAME => 'LeadAds Form Name',
  LeadgenFormFields::FOLLOW_UP_ACTION_URL => '<URL>',
  LeadgenFormFields::QUESTIONS => array(
    (new LeadGenQuestion())->setData(array(
      LeadgenQuestionFields::TYPE => 'EMAIL',
    )),
  ),
  'context_card_id' => <CONTEXT_CARD_ID>,
  'legal_content_id' => <LEGAL_CONTENT_ID>,
));

$form->create();
curl \
  -F 'name=LeadAds Form Name' \
  -F 'follow_up_action_url=<URL>' \
  -F 'questions=[{"type":"EMAIL"}]' \
  -F 'context_card_id=<CONTEXT_CARD_ID>' \
  -F 'legal_content_id=<LEGAL_CONTENT_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_forms

Filter Organic Leads

If you don't want to receive organic leads, you need to make sure you've set block_display_for_non_targeted_viewer to true in your lead form. If you don't restrict organic leads, they appear when you download or request your leads via the API.

use FacebookAds\Object\Fields\LeadgenFormFields;
use FacebookAds\Object\Fields\LeadgenQuestionFields;
use FacebookAds\Object\LeadgenForm;
use FacebookAds\Object\LeadGenQuestion;

$form = new LeadgenForm(null, <PAGE_ID>);
$form->setData(array(
  LeadgenFormFields::NAME => 'LeadAds Form Name',
  LeadgenFormFields::FOLLOW_UP_ACTION_URL => '<URL>',
  LeadgenFormFields::QUESTIONS => array(
    (new LeadGenQuestion())->setData(array(
      LeadgenQuestionFields::TYPE => 'EMAIL',
    )),
  ),
  'block_display_for_non_targeted_viewer' => true,
  'context_card_id' => <CONTEXT_CARD_ID>,
  'legal_content_id' => <LEGAL_CONTENT_ID>,
));

$form->create();
curl \
  -F 'name=LeadAds Form Name' \
  -F 'follow_up_action_url=<URL>' \
  -F 'questions=[{"type":"EMAIL"}]' \
  -F 'block_display_for_non_targeted_viewer=1' \
  -F 'context_card_id=<CONTEXT_CARD_ID>' \
  -F 'legal_content_id=<LEGAL_CONTENT_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_forms

Add Questions

A lead form contains a section that contains headline and list of questions. General features of form questions:

  • You can use question_page_custom_headline to provide a custom headline for the question section of your Lead Form.
  • You can tokenize questions by specifying key; for example, [{type: 'EMAIL', key: 'question1'}]. If keys aren't provided, default to the value formed by concatenating every word in the question by underscore. For example, what_do_you_like.
  • All available question types are listed in the reference docs under questions type.

Create a Standard Question

To create a standard question, you only need to pass the PII type; for example, {type: 'EMAIL'}.

curl \
  -F 'name=LeadAds Form Name' \
  -F 'follow_up_action_url=<URL>' \
  -F 'questions=[{"type":"EMAIL"}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_forms

Create a Custom Text-Input Question

To create a custom text-input question, specify label and type as follows: {label: 'This is a custom text-input question', type: 'CUSTOM'}

curl \
  -F 'name=LeadAds Form Name' \
  -F 'follow_up_action_url=<URL>' \
  -F 'questions=[{"type":"CUSTOM", "label": "This is a custom text-input question"}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_forms

Create a Drop-Down Question

To create a custom drop-down question, specify label, type, and option as follows:

{label: 'This is a custom dropdown question', type: 'CUSTOM', options: [{value: 'option1', key: 'key1'}]}

curl \
  -F 'name=LeadAds Form Name' \
  -F 'follow_up_action_url=<URL>' \
  -F 'questions=[{"type":"CUSTOM", "label": "This is a custom dropdown question", "options": [{value: "option1", key: "key1"}]}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_forms

Add Conditional Questions

To add conditional questions to Lead Forms, you need to upload a CSV file representing all valid options; see the CSV example file for how this file can look like if you use conditional questions to select Country, State, and City.

First create and upload the CSV file. This returns a conditional_questions_group_id.

use FacebookAds\Api;
use FacebookAds\Http\FileParameter;
use FacebookAds\Http\RequestInterface;

$request = $this->getApi()->prepareRequest(
  '/'.<PAGE_ID>.'/leadgen_conditional_questions_group',
  RequestInterface::METHOD_POST);

$request->getFileParams()->offsetSet(
  'conditional_questions_group_csv',
  (new FileParameter('<FILENAME>'))->setMimeType("text/csv"));

$data = $this->getApi()->executeRequest($request)->getContent();
curl \
  -F 'conditional_questions_group_csv=@<FILENAME>;type=text/csv' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_conditional_questions_group

When creating the Lead Form, create a custom questions with a label representing the first column in the CSV file, provide the conditional_questions_group_id and list dependent_conditional_questions in the order you want them selected.

use FacebookAds\Object\Fields\LeadgenFormFields;
use FacebookAds\Object\Fields\LeadgenQuestionFields;
use FacebookAds\Object\LeadgenForm;
use FacebookAds\Object\LeadGenQuestion;

$form = new LeadgenForm(null, $page_id);
$form->setData(array(
  LeadgenFormFields::NAME => 'LeadAds Form Name',
  LeadgenFormFields::FOLLOW_UP_ACTION_URL => '<URL>',
  LeadgenFormFields::QUESTIONS => array(
    (new LeadGenQuestion())->setData(array(
      LeadgenQuestionFields::TYPE => 'EMAIL',
    )),
    (new LeadGenQuestion())->setData(array(
      LeadgenQuestionFields::TYPE => 'CUSTOM',
      LeadgenQuestionFields::LABEL => 'Country',
      'conditional_questions_group_id' => <CONDITIONAL_QUESTIONS_GROUP_ID>,
      'dependent_conditional_questions' => array(
        array('name' => 'State'),
        array('name' => 'City'),
      )
    )),
  ),
  'context_card_id' => <CONTEXT_CARD_ID>,
  'legal_content_id' => <LEGAL_CONTENT_ID>,
));

$form->create();
curl \
  -F 'name=LeadAds Form Name' \
  -F 'follow_up_action_url=<URL>' \
  -F 'questions=[ 
    {"type":"EMAIL"}, 
    { 
      "type": "CUSTOM", 
      "label": "Country", 
      "conditional_questions_group_id": "<CONDITIONAL_QUESTIONS_GROUP_ID>", 
      "dependent_conditional_questions": [{"name":"State"},{"name":"City"}] 
    } 
  ]' \
  -F 'context_card_id=<CONTEXT_CARD_ID>' \
  -F 'legal_content_id=<LEGAL_CONTENT_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/105/leadgen_forms

Create an Appointment Scheduling Question

An appointment scheduling question renders a date-time input with a limited hour selection and a confirmation message below the questions.

To create an appointment scheduling question, specify a label and type. Optionally, you can also add confirmation message in inline_context that will be rendered directly below the question field.

{label: 'Appointment time', type: 'DATE_TIME', inline_context: 'We will verify and call you to confirm your appointment.'}

curl \
  -F 'name=LeadAds Form Name' \
  -F 'follow_up_action_url=<URL>' \
  -F 'questions=[{"type":"DATE_TIME", "label": "Appointment time", "inline_context": "We will verify and call you to confirm your appointment."}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_forms

Create a Store Locator Question

Reference Docs

A store locator question renders a store locator feature based on a user's zip code or postal code input.

To create a store locator question, specify a label, type and context_provider_type as follows:

{label: 'Which dealer do you want to visit?', type: 'STORE_LOOKUP', context_provider_type: 'LOCATION_MANAGER'}

Note: To enable this feature, you must set up the appropriate location structure and map these locations against zip or postal codes.

IPv4 example:

curl \
  -F 'name=LeadAds Form Name' \
  -F 'follow_up_action_url=<URL>' \
  -F 'questions=[{"type":"STORE_LOOKUP", "label": "Which dealer do you want to visit?", "context_provider_type": "LOCATION_MANAGER"}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_forms

Read Lead Form

Read all forms available on a page. See reference doc for available fields; for example, questions.

use FacebookAds\Object\Page;

$page = new Page(<PAGE_ID>);
$leadgen_forms = $page->getLeadgenForms();
from facebookads.adobjects.page import Page

page = Page(<PAGE_ID>)
leadgen_forms = page.get_leadgen_forms()
curl -G \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_forms

Read All Lead Forms

The following API call returns all forms available on a page.

use FacebookAds\Object\Page;

$page = new Page(<PAGE_ID>);
$leadgen_forms = $page->getLeadgenForms();
from facebookads.adobjects.page import Page

page = Page(<PAGE_ID>)
leadgen_forms = page.get_leadgen_forms()
curl -G \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<PAGE_ID>/leadgen_forms

Read All Questions

The following API call returns all available questions on a form:

  • All pre-fill questions
  • All custom created questions
curl \
-F "access_token=ACCESS_TOKEN" \
"https://graph.facebook.com/API_VERSION/FORM_ID?fields=questions"

The category field in the response can be personal, advertiser_customized, or related to a vertical such as automotive.

Archive a Lead Form

You can archive a lead form that's currently used in an ad. An archived form can be activated by setting its status back to ACTIVE. Once a form is archived:

  • The form won't appear (by default) in Forms Library.
  • You can't use an archived form in an ad.
  • Attempting to do so can generate an error via the API.
  • Archived forms won't be available during ad creation in CF or PE.
use FacebookAds\Object\LeadgenForm;
use FacebookAds\Object\Fields\LeadgenFormFields;

$form = new LeadgenForm(<FORM_ID>);
$form->update(array(
  LeadgenFormFields::STATUS => 'ARCHIVED',
));
curl \
  -F 'status=ARCHIVED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<FORM_ID>

Delete a Lead Form

To delete a Lead Form, all ads associated with this form must be deleted or archived.

use FacebookAds\Object\LeadgenForm;

$form = new LeadgenForm(<FORM_ID>);
$form->deleteSelf();
from facebookads.adobjects.leadgenform import LeadgenForm

form = LeadgenForm(<LEADGEN_FORM_ID>)
form.remote_delete()
curl -X DELETE \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<FORM_ID>/

JavaScript Lead Form Builder

This is an optional form-creation dialog to use only if you don't want to use the API. You need the Facebook JavaScript SDK to define a callback that provides necessary data for the Ad Creative. Facebook stores the form at the Page level. You should have ad account permission to open form builder. See Handling the Form Builder, Blog

/**
 * Executing this will immediately load a popup, be sure to
 * associate this with an appropriate event.
 */
FB.ui({
  method: 'lead_gen',
  page_id: <PAGE_ID>,
  ad_account_id: <AD_ACCOUNT_ID>, // Note: This does NOT contain 'act_'
}, function(response) {
  // Handle response.
});

Executing this launches a pop-up:

This create dialog is not supported in mobile devices.

The response:

{
  follow_up_action_text: "<FOLLOW_UP_ACTION_TEXT>",
  follow_up_action_url: "<FOLLOW_UP_ACTION_URL>",
  formID: <FORM_ID>,
  form_url: "<FORM_URL>",
  is_tcpa_compliant: false,
  name: "My+Form",
  pageID: <PAGE_ID>,
  privacy_policy_url: "<PRIVACY_POLICY_URL>",
  status: "success"
}

You only need to provide formID for the object_story_spec for the ad creative. The following are response properties:

Property Name Description Type

custom_disclaimer_responses

The responses to custom disclaimer checkboxes

string

follow_up_action_text

The caption of the follow up action text on the final screen of the form

string

follow_up_action_url

The destination of the follow-up action text on the final screen of the form

string

formID

The ID of the form

string

form_url

The URL to the form

string

is_tcpa_compliant

[DEPRECATED] Whether this form needs TCPA compliance

boolean

name

The name of the form

string

pageID

The ID of the page to which this form belongs

string

privacy_policy_url

The supplied privacy policy URL

string

status

Returns success when the form has been created

string

If you cancel the create, you see the following:

{
  error_code: 4201,
  error_message: "User canceled the Dialog flow"
}

Create Lead Ads

Guidelines on how to set up a campaign and ad set:

  • Campaigns must have objective set to LEAD_GENERATION.
  • Campaign should have buying_type set to AUCTION.
  • Ad sets must have promoted_object set to the corresponding <PAGE_ID>.
  • Ad sets' optimization_goal must be LEAD_GENERATION or LINK_CLICKS. Note that LINK_CLICKS is a sub-optimal optimization strategy and may be deprecated in the future.
  • Ad sets' billing_event should be based on optimization_goal:
  • Billing event IMPRESSIONS for LEAD_GENERATION optimization.
  • Billing event of LINK_CLICKS for LINK_CLICKS optimization.
  • Ad set targeting either mobilefeed or desktopfeed

Ad Creative

The lead ads form builder response contains <FORM_DATA_ID>, which is used to create an ad creative object using an object_story_spec. Note: While creating the link_data, the value associated with the link field can only be https//fb.me/.

While creating the leadgen form using Ads Manager or PE, you don't get the shortened URL, which needs to be supplied under link_data. If this is the case, use the default https://fb.me/ while making the API call.

Ensure that the link_url you specify in the object_story_spec of the creative doesn't belong to a Facebook page; in which case, this API call fails.

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\AdCreativeLinkData;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\Values\AdCreativeCallToActionTypeValues;

$link_data = new AdCreativeLinkData();
$link_data->setData(array(
  AdCreativeLinkDataFields::MESSAGE => 'Creative message',
  AdCreativeLinkDataFields::LINK => 'http://fb.me/',
  AdCreativeLinkDataFields::IMAGE_HASH => '<IMAGE_HASH>',
  AdCreativeLinkDataFields::DESCRIPTION => 'Creative description',
  AdCreativeLinkDataFields::CALL_TO_ACTION => array(
    'type' => AdCreativeCallToActionTypeValues::SIGN_UP,
    'value' => array(
      'lead_gen_form_id' => <FORM_ID>,
    ),
  ),
));

$story = new AdCreativeObjectStorySpec();
$story->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::LINK_DATA => $link_data,
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');
$creative->setData(array(
  AdCreativeFields::OBJECT_STORY_SPEC => $story,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreativelinkdata import AdCreativeLinkData
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec

link_data = AdCreativeLinkData()
link_data[AdCreativeLinkData.Field.message] = 'try it out'
link_data[AdCreativeLinkData.Field.link] = 'http://fb.me/'
link_data[AdCreativeLinkData.Field.image_hash] = '<IMAGE_HASH>'
link_data[AdCreativeLinkData.Field.description] = 'My caption'
link_data[AdCreativeLinkData.Field.call_to_action] = {
    'type': 'SIGN_UP',
    'value': {
        'lead_gen_form_id': <FORM_ID>,
    },
}

object_story_spec = AdCreativeObjectStorySpec()
object_story_spec[AdCreativeObjectStorySpec.Field.page_id] = <PAGE_ID>
object_story_spec[AdCreativeObjectStorySpec.Field.link_data] = link_data

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.name] = 'AdCreative for Link Ad'
creative[AdCreative.Field.object_story_spec] = object_story_spec
creative.remote_create()

print(creative)
curl \
  -F 'object_story_spec={ 
    "link_data": { 
      "call_to_action": {"type":"SIGN_UP","value":{"lead_gen_form_id":"<FORM_ID>"}}, 
      "description": "Creative description", 
      "image_hash": "<IMAGE_HASH>", 
      "link": "http:\/\/fb.me\/", 
      "message": "Creative message" 
    }, 
    "page_id": "<PAGE_ID>" 
  }' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.9/act_<AD_ACCOUNT_ID>/adcreatives

Call to Action

The following call-to-action (CTA) types are available: APPLY_NOW, DOWNLOAD, GET_QUOTE, LEARN_MORE, SIGN_UP, SUBSCRIBE

You can create a carousel lead ad using the same object_story_spec, but with an additional lead_gen_form_id field defined in the child_attachments.

You can only specify the same <FORM_ID> for all child attachments.

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataChildAttachmentFields;
use FacebookAds\Object\Values\AdCreativeCallToActionTypeValues;

$child_attachments = array();

for ($i = 0; $i <= 3; $i++) {
  $child_attachments[] = array(
    AdCreativeLinkDataChildAttachmentFields::LINK => $url,
    AdCreativeLinkDataChildAttachmentFields::IMAGE_HASH => '<IMAGE_HASH>',
    AdCreativeLinkDataChildAttachmentFields::CALL_TO_ACTION => array(
      'type' => AdCreativeCallToActionTypeValues::SIGN_UP,
      'value' => array(
        'lead_gen_form_id' => <FORM_ID>,
      ),
    ),
  );
}

$object_story_spec = array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::LINK_DATA => array(
    AdCreativeLinkDataFields::MESSAGE => 'My description',
    AdCreativeLinkDataFields::LINK => $url,
    AdCreativeLinkDataFields::CAPTION => 'WWW.EXAMPLE.COM',
    AdCreativeLinkDataFields::CHILD_ATTACHMENTS => $child_attachments,
    AdCreativeLinkDataFields::MULTI_SHARE_OPTIMIZED => true,
    AdCreativeLinkDataFields::CALL_TO_ACTION => array(
      'type' => AdCreativeCallToActionTypeValues::SIGN_UP,
      'value' => array(
        'lead_gen_form_id' => <FORM_ID>,
      ),
    ),
  ),
);

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');
$creative->setData(array(
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreativelinkdata import AdCreativeLinkData
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec
from facebookads.adobjects.adcreativelinkdatachildattachment \
    import AdCreativeLinkDataChildAttachment

child_attachments = list()
for i in range(3):
    child_attachment = AdCreativeLinkDataChildAttachment()
    child_attachment[AdCreativeLinkDataChildAttachment.Field.link] = 'http://fb.me/'
    child_attachment[AdCreativeLinkDataChildAttachment.Field.image_hash] = '<IMAGE_HASH>'
    child_attachment[AdCreativeLinkDataChildAttachment.Field.image_hash] = '<IMAGE_HASH>'
    child_attachment[AdCreativeLinkDataChildAttachment.Field.call_to_action] = {
        'type': 'SIGN_UP',
        'value': {
            'lead_gen_form_id': <FORM_ID>,
        },
    }
    child_attachments.append(child_attachment)

link_data = AdCreativeLinkData()
link_data[AdCreativeLinkData.Field.message] = 'My description'
link_data[AdCreativeLinkData.Field.link] = 'http://fb.me/'
link_data[AdCreativeLinkData.Field.caption] = 'WWW.EXAMPLE.COM'
link_data[AdCreativeLinkData.Field.child_attachments] = child_attachments
link_data[AdCreativeLinkData.Field.multi_share_optimized] = True
link_data[AdCreativeLinkData.Field.call_to_action] = {
    'type': 'SIGN_UP',
    'value': {
        'lead_gen_form_id': <FORM_ID>,
    },
}

story = AdCreativeObjectStorySpec()
story[story.Field.page_id] = <PAGE_ID>
story[story.Field.link_data] = link_data

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.object_story_spec] = story

creative.remote_create()
curl \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "link_data": { 
      "message": "My description", 
      "link": "http:\/\/www.google.com", 
      "caption": "WWW.EXAMPLE.COM", 
      "child_attachments": [ 
        { 
          "link": "http:\/\/www.google.com", 
          "image_hash": "<IMAGE_HASH>", 
          "call_to_action": {"type":"SIGN_UP","value":{"lead_gen_form_id":"<FORM_ID>"}} 
        }, 
        { 
          "link": "http:\/\/www.google.com", 
          "image_hash": "<IMAGE_HASH>", 
          "call_to_action": {"type":"SIGN_UP","value":{"lead_gen_form_id":"<FORM_ID>"}} 
        }, 
        { 
          "link": "http:\/\/www.google.com", 
          "image_hash": "<IMAGE_HASH>", 
          "call_to_action": {"type":"SIGN_UP","value":{"lead_gen_form_id":"<FORM_ID>"}} 
        }, 
        { 
          "link": "http:\/\/www.google.com", 
          "image_hash": "<IMAGE_HASH>", 
          "call_to_action": {"type":"SIGN_UP","value":{"lead_gen_form_id":"<FORM_ID>"}} 
        } 
      ], 
      "multi_share_optimized": true, 
      "call_to_action": {"type":"SIGN_UP","value":{"lead_gen_form_id":"<FORM_ID>"}} 
    } 
  }' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.9/act_<AD_ACCOUNT_ID>/adcreatives

Video

You can also use a video in the lead ad creative instead of a photo. First, upload the video to your ad video library, and then use it in the object_story_spec:

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\AdCreativeVideoData;
use FacebookAds\Object\Fields\AdCreativeVideoDataFields;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Values\AdCreativeCallToActionTypeValues;

$video_data = new AdCreativeVideoData();
$video_data->setData(array(
  AdCreativeVideoDataFields::LINK_DESCRIPTION => 'try it out',
  AdCreativeVideoDataFields::IMAGE_URL => '<THUMBNAIL_URL>',
  AdCreativeVideoDataFields::VIDEO_ID => <VIDEO_ID>,
  AdCreativeVideoDataFields::CALL_TO_ACTION => array(
    'type' => AdCreativeCallToActionTypeValues::SIGN_UP,
    'value' => array(
      'link' => 'http://fb.me/',
      'lead_gen_form_id' => <FORM_ID>,
    ),
  ),
));

$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::VIDEO_DATA => $video_data,
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');

$creative->setData(array(
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec
from facebookads.adobjects.adcreativevideodata \
    import AdCreativeVideoData

video_data = AdCreativeVideoData()
video_data[AdCreativeVideoData.Field.link_description] = 'My Description'
video_data[AdCreativeVideoData.Field.video_id] = <VIDEO_ID>
video_data[AdCreativeVideoData.Field.image_url] = '<IMAGE_URL>'
video_data[AdCreativeVideoData.Field.call_to_action] = {
    'type': 'SIGN_UP',
    'value': {
        'link': 'http://fb.me/',
        'lead_gen_form_id': <FORM_ID>,
    },
}

object_story_spec = AdCreativeObjectStorySpec()
object_story_spec[AdCreativeObjectStorySpec.Field.page_id] = <PAGE_ID>
object_story_spec[AdCreativeObjectStorySpec.Field.video_data] = video_data

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.object_story_spec] = object_story_spec
creative.remote_create()
curl \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "video_data": { 
      "call_to_action": { 
        "type": "SIGN_UP", 
        "value": {"link":"http:\/\/fb.me\/","lead_gen_form_id":"<FORM_ID>"} 
      }, 
      "image_url": "<THUMBNAIL_URL>", 
      "link_description": "try it out", 
      "video_id": "<VIDEO_ID>" 
    } 
  }' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

The resulting creative id returned by the previous call is then used to create an Ad.

use FacebookAds\Object\Ad;
use FacebookAds\Object\Fields\AdFields;

$data = array(
  AdFields::NAME => 'My Ad',
  AdFields::ADSET_ID => <AD_SET_ID>,
  AdFields::CREATIVE => array(
    'creative_id' => <CREATIVE_ID>,
  ),
);

$ad = new Ad(null, 'act_<AD_ACCOUNT_ID>');
$ad->setData($data);
$ad->create(array(
  Ad::STATUS_PARAM_NAME => Ad::STATUS_PAUSED,
));
from facebookads.adobjects.ad import Ad

ad = Ad(parent_id='act_<AD_ACCOUNT_ID>')
ad[Ad.Field.name] = 'My Ad'
ad[Ad.Field.adset_id] = <AD_SET_ID>
ad[Ad.Field.creative] = {
    'creative_id': <CREATIVE_ID>,
}
ad.remote_create(params={
    'status': Ad.Status.paused,
})
Ad ad = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAd()
  .setName("My Ad")
  .setAdsetId(<AD_SET_ID>)
  .setCreative(
    new AdCreative()
      .setFieldId(<CREATIVE_ID>)
  )
  .setStatus(Ad.EnumStatus.VALUE_PAUSED)
  .execute();
curl \
  -F 'name=My Ad' \
  -F 'adset_id=<AD_SET_ID>' \
  -F 'creative={"creative_id":"<CREATIVE_ID>"}' \
  -F 'status=PAUSED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/ads

Create Leadgen Plugin

You can use the Create Leadgen plugin to provide the Facebook Leadgen creation UI flow in your website. For details about the UI component, see Dialogs.

Set up the Facebook SDK for JavaScript, see:

Then trigger the Create Leadgen page:

FB.ui({         
  account_id: '<ACCOUNT_ID>',
  display: 'popup',
  method: 'lead_gen',
  page_id: '<PAGE_ID>',
}, function(response) {
  // callback
});

You can provide these settings for the plugin:

Name Description

account_id

Your ad account ID

display

popup

method

lead_gen

page_id

Your page ID

The plugin provides this response on success:

Struct {
  formID: numeric string,
  status: bool,
  ...
}