Available for Facebook desktop and mobile (Feed, Stories, Marketplace) and Instagram (Feed, Stories, Reels, Profile Feed, Explore Home, Profile Reels).
To create Advantage+ catalog ads for this objective, your page must use Facebook Locations.
objective
set to STORE_VISITS
.promoted_object
set to the corresponding <PARENT_PAGE_ID>
.promoted_object
and targeting
must contain a place_page_set_id
of a <PAGE_SET_ID>
optimization_goal
must be set to REACH
billing_event
should be IMPRESSIONS
PageSet
Facebook uses PageSet
to target ads and uses it as the promoted object in your ad.
To create a PageSet
:
PageSet
with the Locations JSON structure.The <PARENT_PAGE_ID>
is the page ID for the main page for all your store locations. It retrieves all store pages and locations that belong to the main page and returns the longitude and latitude for each location:
curl -X GET \ -d 'fields="location{latitude,longitude},is_permanently_closed"' \ -d 'limit=30000' \ -d 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/<API_VERSION>/<PARENT_PAGE_ID>/locations
Example output
{ "data": [ { "location": { "latitude": 29.173384, "longitude": 48.098807 }, "is_permanently_closed": false, "id": "1788030244802584" }, { "location": { "latitude": 29.303635, "longitude": 47.937725 }, "is_permanently_closed": false, "id": "261533444245300" }, { "location": { "latitude": 29.302303, "longitude": 47.933178 }, "is_permanently_closed": false, "id": "179435399132774" }, { "location": { "latitude": 29.302591, "longitude": 47.931801 }, "is_permanently_closed": false, "id": "1790317704582144" } ], "paging": { "cursors": { "before": "MTc4ODAzMDI0NDgwMjU4NAZDZD", "after": "MTA4MTU4NjU5NjA5MDA4" } } }
Iterate through each entry in the returned results and verify each location is open for business by checking the is_permanently_closed
field.
Get the estimated radius using two GET
requests to obtain the radius
and distance_unit
parameters. Alternatively, you can make a batch API call to generate the values below.
You should make this request using each store page's latitude and longitude from the JSON results returned from the main page. This returns the estimated radius for each location.
curl -X GET \ -d 'type="adradiussuggestion"' \ -d 'latitude=51.5152253' \ -d 'longitude=-0.1423029' \ -d 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v20.0/search/
You can also batch multiple requests into a single request.
curl \ -F "access_token=<ACCESS_TOKEN>" \ -F "include_headers=false" \ -F "batch=[ { \"method\": \"GET\", \"relative_url\": \"/<API_VERSION>/search?type=adradiussuggestion&latitude=29.173384&longitude=48.098807\" }, { \"method\": \"GET\", \"relative_url\": \"/<API_VERSION>/search?type=adradiussuggestion&latitude=29.303635&longitude=47.937725\" } ]" \ "https://graph.facebook.com"
Use the radius
and distance_unit
parameters obtained from the previous calls along with each location's <CHILD_LOCATION_ID>
as the page_id
to create the final Locations JSON structure.
[ { "page_id": 1788030244802584, "radius": 1, "distance_unit": "mile" }, { "page_id": 261533444245300, "radius": 1, "distance_unit": "mile" } ]
Pageset
with the Locations JSON structureThe PageSet
endpoint is currently only available to Partners on the allow list. Please contact your Facebook representative for access.
You can now create a PageSet
with the information in your Locations JSON structure.
The maximum number of locations that can be used in a PageSet
is 10,000.
You can make an asynchronous request to create your PageSet
. This enables you to create large PageSets
with more than 1,000 locations without experiencing timeouts. We recommend you use asynchronous requests whenever you create a Pageset
with over 50 locations.
Request
curl -X POST \ -d 'name=<AD_SET_NAME>' \ -d 'parent_page=<PARENT_PAGE_ID>' \ -d 'pages=[{"page_id":<CHILD_PAGE_ID>}]' \ -d 'metadata={"audience":{"size":<AUDIENCE_SIZE>}}' \ -d 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/ad_place_page_sets_async/
Note: You can use /ad_place_page_sets
for synchronous requests; however, you should use asynchronous requests for more than 50 locations.
The format for parameters are the same as those you use for synchronous requests.
Inside your PageSet
, you can use the metadata
field to specify a fixed radius per location for your ads delivery or to reach a certain audience size. If you select the latter, Facebook automatically calculates a radius per location to reach that number of Accounts Center accounts.
In this example, the metadata
field is set to a desired audience
size. See metadata
for Radiuses. This returns an ad_place_page_set_async_request
ID.
{ "id": "405738580111111" }
Later, you can query that ID with the ads_read
permission to get the PageSet
ID.
curl -i -X GET \ "https://graph.facebook.com/<API_VERSION>/405738580111111?access_token=ACCESS_TOKEN"
Example Output
{ "id": "405738580111111", "place_page_set": { "id": "555555791481678", "name": "test_ad_set" }, "progress": 1 }
Where progress
is from 0.0
to 1
, and 1
means we completed your request and created a PageSet
.
metadata
for radiusesThe metadata
field tells Facebook you want to use a fixed radius for your locations or you want Facebook to automatically calculate radiuses per location based on a given audience size.
Request
To specify a fixed radius using a synchronous request:
curl -X POST \ -d 'name=<PAGE_SET_NAME>' \ -d 'parent_page=<PARENT_PAGE_ID>' \ -d 'pages=[{"page_id":<CHILD_PAGE_ID>}]' \ -d 'metadata={"fixed_radius":{"value":5,"distance_unit":"mile"}}' \ -d 'access_token=ACCESS_TOKEN' \ https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/ad_place_page_sets/
This means you want Facebook to deliver your ad to people within a 5-mile radius of all locations in your PageSet
.
Example Output
{ "id": "1618547271777777" }
Note: The metadata
field should be set to either fixed_radius
or audience
.
If you use fixed_radius
, you need to provide distance_unit
and value
:
{ "fixed_radius": { "distance_unit": "<distance_unit>", "value": <distance> } }
If you use audience
, you need to provide size
while max_radius
is optional
Note: this only works with ad_place_page_sets_async
{ "audience": { "size": <audience_size>, "max_radius": { // optional "distance_unit": "<distance_unit>", "value": <distance> } } }
Best Practices for metadata
locations
; however, do not specify a radius in it. Alternately, if you use the locations
parameter and provide radiuses, you should not also provide it for metadata
.distance_unit
must be mile
or kilometer
, and the value
must be between 0.7
to 50
for mile
or 1
to 80
for kilometer
.size
parameter in audience
is the number of Accounts Center accounts in the radius as long as the radius is from 1
to 80
kilometers in length. If you provide a max_radius
, the actual radius we calculate varies between 1
and max_radius
.audience
for metadata
, you must make your request with the asynchronous endpoint (ad_account_ID/ad_place_page_set_async
).You can still use synchronous requests to create a PageSet
.
curl -X POST \ -d "name=<PAGESET_NAME>" \ -d "parent_page=<PARENT_PAGE_ID>" \ -d "pages=<LOCATIONS_JSON_STRUCTURE>" \ -d "access_token=<ACCESS_TOKEN>" \ https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/ad_place_page_sets
This returns a PageSet
ID that you will use later.
Example Output
{ "id": <PAGE_SET_ID> }
If the number of pages is too large for a cURL
call, you can create a text file containing the Locations JSON structure and pass it to the pages
attribute with -F "pages=<locations_json_structure.txt"
.
Create an ad campaign with the objective set to STORE_VISITS
and your main page ID as the promoted object.
Create an ad set to contain your ad. See Reference, Ad Set, Reference, Targeting specs and Reference, Page locations.
At delivery time, Facebook invalidates any ads targeting locations more than 50 miles away from the nearest page location, known as a local page.
curl \ -F 'name=Store Visits Ad Set' \ -F 'promoted_object={"place_page_set_id":"<PAGE_SET_ID>"}' \ -F 'optimization_goal=REACH' \ -F 'billing_event=IMPRESSIONS' \ -F 'is_autobid=true' \ -F 'daily_budget=1000' \ -F 'campaign_id=<CAMPAIGN_ID>' \ -F "targeting={ 'age_min' : <MIN_AGE>, 'age_max' : <MAX_AGE>, 'place_page_set_ids': ['<PAGE_SET_ID>'], 'device_platforms': ['mobile','desktop'], 'facebook_positions': ['feed'] }" \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adsets
You can also target by geo_locations
in store traffic campaigns.
Note: For this objective, you can only use geo_locations
or place_page_set_ids
in ad set targeting.
We support all types of geo_location
targeting in Advanced Targeting and Placement, including targeting by countries, cities, and zip codes. You can also select location_types
, such as recent
, home
, or travel_in
.
You should still provide place_page_set_id
in the promoted_object
. This PageSet
has to be a page set without any explicit set of locations. See Creating the PageSet with the Locations JSON struture to create this PageSet
. However, in this case, do not pass the parameter pages.
First, create a PageSet
you will later provide in a promoted object:
curl -X POST \ -d "name=My geo targeting page set" \ -d "parent_page=<PARENT_PAGE_ID>" \ -d "access_token=<ACCESS_TOKEN>" \ https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/ad_place_page_sets/
Note: You do not need to provide the pages
parameter as you normally do.
Then, create an ad set with the store traffic objective targeting geo_locations
:
curl \ -F 'name=Store Traffic Ad Set' \ -F 'promoted_object={"place_page_set_id":"<PAGE_SET_ID>"}' \ -F 'optimization_goal=REACH' \ -F 'billing_event=IMPRESSIONS' \ -F 'is_autobid=true' \ -F 'daily_budget=1000' \ -F 'campaign_id=<CAMPAIGN_ID>' \ -F "targeting={ 'geo_locations': {"countries":["US"],"location_types": ["home"]}, 'device_platforms': ['mobile','desktop'], 'facebook_positions': ['feed'] }" \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adsets
We automatically deliver ads for the store which is closest to the person viewing your ad.
You can dynamically insert a creative based on someone's location. Customize your creative using a set of template placeholders and Facebook replaces the placeholders in your ads at runtime with data from the nearest page location.
Available placeholders:
{{page.hours.today}}
{{page.location.city}}
{{page.location.region}}
{{page.location.postcode}}
{{page.location.street_address}}
{{page.name}}
{{page.phone_number}}
The dynamic_ad_voice
field allows you to control the voice of your ad:
dynamic_ad_voice
is set to DYNAMIC
, The page name and profile picture in your ad post come from the nearest page location.dynamic_ad_voice
is set to STORY_OWNER
, he page name and profile picture in your ad post come from the main page location.You can also dynamically add call-to-action buttons (CTAs) based on someone's location:
GET_DIRECTIONS
or CALL_NOW
, the CTA value
field is not required. Users will automatically be directed to nearest location or prompted to call the nearest location phone number. MESSAGE_PAGE
is allowed only if dynamic_ad_voice
is set to STORY_OWNER
. Messages will be delivered to the main page.Like Page
button.For details, see Reference, Ad Creative
dynamic_ad_voice Type
| call_to_action Type
|
---|---|
|
|
|
|
Provide an ad creative using a dynamic page name and city:
curl \ -F 'dynamic_ad_voice=DYNAMIC' \ -F 'object_story_spec={ "page_id": "<PARENT_PAGE_ID>", "template_data": { "description": "Ad Description", "link": "<URL>", "message": "Ad Message for {{page.location.city}}", "name": "{{page.name}}", "picture": "<IMAGE_URL>" } }' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adcreatives
To use a map card, add a place_data
structure as a attachment in the child_attachments
field for your ad creative.
In this example, the map with a Facebook store locator link is the second item in the child_attachments
array. You must provide have at least one item in addition to the map card.
curl \ -F 'dynamic_ad_voice=DYNAMIC' \ -F 'object_story_spec={ "page_id": "<PARENT_PAGE_ID>", "template_data": { "description": "Ad Description", "link": "<URL>", "message": "Ad Message for {{page.location.city}}", "name": "{{page.name}}", "child_attachments":[ { "description": "Come visit us!", "link": "http://yourweburl.com", "name": "{{page.location.street_address}} - {{page.location.city}}", "call_to_action": { "type":"GET_DIRECTIONS" }, }, { "link": "https://fb.com/store_locator", "name": "Check out our stores.", "place_data": { "type":"DYNAMIC" }, } ] } }' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adcreatives
When you create an ad, if you set the link
to 'https://fb.com/store_locator', the ad appears with the store locator as the link destination.
Create an ad as follows:
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/<API_VERSION>/act_<AD_ACCOUNT_ID>/ads
To create ads for store traffic, your page and ad account must be approved for the store visits measurement. Otherwise, an error similar to Reach estimate isn't available because 'store_visits' isn't a valid action type
displays.
Store visits is an estimated metric based on data from users with location services enabled. It ultimately offers store visit measurement and optimization for the store traffic objective. Store visit measurement is only available for campaigns with the store traffic objective.
Store visits are based on clicks and views of ads using the store traffic objective. It's an estimated number of visits to an advertiser's stores by Accounts Center accounts who have seen or clicked on each store's ads. You can configure the attribution window; you can choose to customize it based on 1-, 7- or 28-day clicks or views. The ad account's default attribution applies unless you customize the configuration. See Insights API, Attribution Window.
The features relate to reporting for the following items:
See the columns under ENGAGEMENT: ACTIONS
. These columns appear in the reporting interface for store visits and the cost per store visit.
Note: Store visit data is only available for stores that Meta team confirms as measurable for a campaign.
You can get data on store visits from the Insights API. We provide these additional fields in the general insights calls: cost_per_store_visit_action
and store_visit_actions
. See Insights, Reference.
Field | Description |
---|---|
point_estimate int32 | The point prediction of the value |