@saltcorn/meta-marketing-api 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -136,6 +136,10 @@ a different token.
136
136
  | `get_meta_ad_headline(ad)` | The headline of an ad, from an ad id or an ad you have already read |
137
137
  | `get_meta_ad_body(ad)` | The primary text of an ad: the longer wording above the image |
138
138
  | `get_meta_ad_text(ad)` | Both of the above together, as `{ headline, body }`, in one read |
139
+ | `get_meta_ad_media(ad, options)` | What an ad is made of and where to download it |
140
+ | `get_meta_ad_media_type(ad)` | Whether an ad is an `image`, a `video`, `mixed` or `unknown` |
141
+ | `get_meta_ad_media_url(ad)` | The address of the picture or the film in an ad |
142
+ | `get_meta_page_access_token(pageId)` | A token for one of your pages, or nothing when you have no access to it |
139
143
  | `get_meta_ad_preview(adId, adFormat)` | A ready made HTML preview of an ad |
140
144
  | `get_meta_insights(objectId, query)` | Performance figures for an account, campaign, ad set or ad |
141
145
  | `get_meta_insights_async(objectId, query)` | The same, run as a background report, for large date ranges |
@@ -177,11 +181,149 @@ get_meta_ad_text(ad_id)
177
181
 
178
182
  which gives you `{ headline: "...", body: "..." }`, where the body is the
179
183
  longer text above the image. For an ad that is boosting a post already on
180
- your page, the wording belongs to the post rather than to the ad, and reading
181
- it needs a token that can also read the page. When it cannot be read you get
184
+ your page, the wording belongs to the post rather than to the ad; the module
185
+ asks Meta for a token for that page and reads it with that, which needs the
186
+ access token in the settings to have a say over the page, as described under
187
+ *Ads that boost a post on your page* below. When it cannot be read you get
182
188
  empty text back rather than an error; `get_meta_ad_preview` will still show
183
189
  you the ad as it appears.
184
190
 
191
+ ### The picture or the film in an ad
192
+
193
+ `get_meta_ad_media` tells you what kind of ad you are looking at and where to
194
+ download the file it is built on:
195
+
196
+ ```
197
+ get_meta_ad_media(ad_id)
198
+ ```
199
+
200
+ gives you
201
+
202
+ ```
203
+ {
204
+ type: "video",
205
+ carousel: false,
206
+ media: [
207
+ {
208
+ kind: "video",
209
+ video_id: "1234",
210
+ url: "https://video.xx.fbcdn.net/...",
211
+ thumbnail_url: "https://scontent.xx.fbcdn.net/...",
212
+ permalink_url: "...",
213
+ length: 15
214
+ }
215
+ ],
216
+ creative_id: "5678",
217
+ object_type: "VIDEO",
218
+ thumbnail_url: "https://scontent.xx.fbcdn.net/...",
219
+ from_post: false,
220
+ error: undefined
221
+ }
222
+ ```
223
+
224
+ - **type** is `image`, `video`, `mixed` or `unknown`. `mixed` means the ad
225
+ offers Meta both to choose between, which is what a flexible or dynamic
226
+ creative does, or a carousel with both in it. `unknown` means there is no
227
+ picture or film to be found, as on a text only ad.
228
+ - **carousel** says whether the ad holds more than one card. The cards are
229
+ the entries in `media`, in the order they are shown.
230
+ - **media** has one entry per picture or film, each with a `url` you can
231
+ download. The still that a film shows before it plays is on that film's
232
+ entry as `thumbnail_url`, and does not count as a picture of its own. An
233
+ entry that could not be reached has no `url` and carries an `error` saying
234
+ why instead.
235
+ - **thumbnail_url** is a picture of the ad as it appears. It is there even
236
+ when nothing else is, so it is worth keeping as a fallback: for a film it
237
+ is a still rather than the film itself, which is why it is not in `media`.
238
+ - **from_post** says the ad is boosting a post that was already on your page,
239
+ so the media was read from the post rather than from the ad.
240
+ - **error** is there only when something could not be read, and says what.
241
+ An ad never stops a run over an ad set because of it: you get `unknown`
242
+ and the reason.
243
+
244
+ ### Ads that boost a post on your page
245
+
246
+ Much of what is advertised on Facebook and Instagram is a post that already
247
+ exists on a page. Such an ad keeps nothing on the creative but the id of the
248
+ page and of the post:
249
+
250
+ ```
251
+ {
252
+ "object_type": "SHARE",
253
+ "object_story_spec": { "page_id": "1067...", "instagram_user_id": "1784..." },
254
+ "effective_object_story_id": "1067..._1334..."
255
+ }
256
+ ```
257
+
258
+ The picture or the film is on the post, and Meta only shows a post to a token
259
+ that carries that page's own permissions. `get_meta_ad_media` asks for a
260
+ token for the page by itself and reads the post with it, so these ads work
261
+ like any other, as long as the access token in the settings has a say over
262
+ the page. That means:
263
+
264
+ - the token must have the **pages_read_engagement** permission, and
265
+ - the person or system user it belongs to must have a role on that page. In
266
+ Business Manager, add the page to the same business as the ad account and
267
+ give the system user access to it.
268
+
269
+ When that is missing you get `type: "unknown"` and an `error` saying so,
270
+ rather than silence. To check one page on its own:
271
+
272
+ ```
273
+ get_meta_page_access_token("106755536029753")
274
+ ```
275
+
276
+ Nothing back means the token has no say over that page. `thumbnail_url` is
277
+ still filled in for these ads, so you have a picture of the ad to look at
278
+ even when the post itself cannot be read.
279
+
280
+ A few things are worth knowing before you download:
281
+
282
+ - **Video addresses are signed and short lived.** Fetch the file as soon as
283
+ you have the address rather than storing the address for later. Meta only
284
+ gives the address out to a token that owns the video: with a read only
285
+ token you may get the video's id and its thumbnail but no `url`, and the
286
+ entry then carries an `error` saying why. `permalink_url` is a stable
287
+ address for watching it, not for downloading it.
288
+ - **Working out the type is cheaper than finding the addresses.** Every film
289
+ costs one extra read to look up. If all you want is image against video,
290
+ use `get_meta_ad_media_type`, or pass the options `{ resolve_urls: false }`.
291
+ - **Pictures are often named by a hash rather than by an address.** The
292
+ address is then held by the ad account's own picture library, which is
293
+ looked up for you, so reading ads of a second ad account works better when
294
+ you pass that account's id: `get_meta_ad_media(ad, { account_id: "..." })`,
295
+ or read the ads with `account_id` among the fields. When the library does
296
+ not hold the picture and the ad boosts a post, the post is read instead.
297
+ - **An ad whose creative shows no media is read again in full.** You may have
298
+ asked Meta for only some of the places media can hide, so rather than
299
+ answer `unknown` too readily it asks for all of them. Handing it an ad you
300
+ read with the creative fields below saves that second read.
301
+
302
+ To go through a whole ad set:
303
+
304
+ ```
305
+ const ads = await get_meta_adset_ads(adset_id, {
306
+ fields:
307
+ "id,name,account_id,creative{id,name,object_type,image_url,image_hash," +
308
+ "video_id,thumbnail_url,object_story_spec,asset_feed_spec," +
309
+ "effective_object_story_id}"
310
+ });
311
+ for (const ad of ads) {
312
+ const { type, media } = await get_meta_ad_media(ad);
313
+ console.log(ad.name, type, media.map((m) => m.url));
314
+ }
315
+ ```
316
+
317
+ Asking for those creative fields is worth doing on a loop like this: given an
318
+ ad that already carries them, `get_meta_ad_media` works from what you have
319
+ instead of reading each ad again. Given only an ad id, it asks for them
320
+ itself.
321
+
322
+ Ads read as a table row, or by `get_meta_ads` without a `fields` of your own,
323
+ carry `creative_object_type`. That is a rough answer on its own: most ads
324
+ that link somewhere are reported as `SHARE` whether the media is a picture or
325
+ a film, so use `get_meta_ad_media` when it matters.
326
+
185
327
  ## Things to know
186
328
 
187
329
  - **Money is in cents.** Budgets, bids and amounts spent come from Meta as