Creating Lead Forms and Ads

This document describes how you can create and manage Lead Forms and how to create Lead Ads through the API. Before creating a Lead Form, you need to create Legal Content and Context Card (Optional). Please 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 retreive 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.10/<PAGE_ID>/leadgen_legal_content

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.10/<PAGE_ID>/leadgen_context_cards

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/VERSION/PAGE_ID/leadgen_thank_you_page"

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

  • body - The body of the thank you page
  • business_phone_number - Phone number with full international number
  • button_text - Text shown on the call-to-action button of static footer
  • button_type - This must be of type {'VIEW_WEBSITE', "DOWNLOAD"}
  • country_code - The two-letter ISO country code which representations a country
  • enable_messenger - Whether to allow users to message business
  • title - Title of the thank you Page
  • website_url - URL of website where Facebook redirections someone when they click the call-to-action

Create Lead Form

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

Features in form questions:

  • You can use question_page_custom_headline to provide a custom headline for the question section of your Lead Form.
  • For standard questions you only need to pass PII type such as {type: 'EMAIL'} to create a standard question.
  • For custom questions, specify labels and types as follows {label: 'This is a standard question', type: 'CUSTOM'}.
  • You can tokenize questions by specifying key, for example [{type: 'EMAIL', key: 'question1'}]. If keys are not provided, we default to the value formed by concatenating every word in the question by underscore. For example, what_do_you_like.
  • To specify a dropdown custom question, use an additional field called options. The options field is an array and should be passed as follows [{value: 'option1'}, {value: 'option2'}]. You can tokenize options by specifying 'key' for example [{value: 'option1', key: 'key1'}].
  • All available question types are listed in the reference docs under questions type.
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.10/<PAGE_ID>/leadgen_forms

Filtering Organic Leads

If you don't want to receive organic leads, you'll 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.10/<PAGE_ID>/leadgen_forms

Conditional Questions

To add conditional questions to Lead Forms, you will need to upload a CSV file representing all valid options, see the CSV example file for how this file can look like if we are using 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.10/<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"}, 
    { 
      "conditional_questions_group_id": "<CONDITIONAL_QUESTIONS_GROUP_ID>", 
      "dependent_conditional_questions": [{"name":"State"},{"name":"City"}], 
      "label": "Country", 
      "type": "CUSTOM" 
    } 
  ]' \
  -F 'context_card_id=<CONTEXT_CARD_ID>' \
  -F 'legal_content_id=<LEGAL_CONTENT_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/105/leadgen_forms

Read Lead Form

Read all forms available on a page, see reference doc for available fields, e.g. 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.10/<PAGE_ID>/leadgen_forms

Archive Lead Form

You can archive a form that is 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 cannot use an archived form in an ad
  • Attempting to do so will raise 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.10/<FORM_ID>

Reading 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.10/<PAGE_ID>/leadgen_forms

Reading 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.

Deleting 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.10/<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 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 popup:

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 or not 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

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 will be used to create an ad creative object using an object_story_spec. Note that, while creating the link_data, the value associated with link field can only be https//fb.me/.

While creating the leadgen form using Ads Manager or PE, you will not receive the shortened URL which needs to be supplied under link_data. For such cases where you don't have the shortened form URL, 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 does not belong to a Facebook Page, in which case this api call will fail.

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 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 then you can 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.10/act_<AD_ACCOUNT_ID>/adcreatives

The resulting creative id returned by the previous call will then be 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.10/act_<AD_ACCOUNT_ID>/ads