@saltcorn/meta-marketing-api 0.1.0
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/LICENSE +21 -0
- package/README.md +180 -0
- package/api.js +561 -0
- package/common.js +449 -0
- package/index.js +516 -0
- package/package.json +36 -0
- package/sync-action.js +337 -0
- package/table-provider.js +351 -0
- package/tests/api.test.js +94 -0
- package/tests/common.test.js +186 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Saltcorn
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# meta-marketing-api
|
|
2
|
+
|
|
3
|
+
Read your Facebook and Instagram advertising into Saltcorn, using the Meta
|
|
4
|
+
Marketing API.
|
|
5
|
+
|
|
6
|
+
This module is read only: it never creates, changes, pauses or deletes
|
|
7
|
+
anything in your Meta ad accounts. It brings your campaigns, ad sets, ads,
|
|
8
|
+
creatives and their performance figures into Saltcorn, where you can build
|
|
9
|
+
your own views, dashboards and reports on top of them.
|
|
10
|
+
|
|
11
|
+
## Before you start
|
|
12
|
+
|
|
13
|
+
You need an access token that is allowed to read your ads. The most reliable
|
|
14
|
+
kind is a **system user token** from Meta Business Manager, because it does
|
|
15
|
+
not expire:
|
|
16
|
+
|
|
17
|
+
1. In [Meta Business Manager](https://business.facebook.com/), go to
|
|
18
|
+
**Business settings → Users → System users** and add a system user.
|
|
19
|
+
2. Give that system user access to the ad account you want to read, with the
|
|
20
|
+
*View performance* (analyst) role or better.
|
|
21
|
+
3. Choose **Generate new token**, pick your Meta app, and tick the
|
|
22
|
+
`ads_read` permission.
|
|
23
|
+
4. Copy the token. This is the only time it is shown.
|
|
24
|
+
|
|
25
|
+
A personal access token from the [Graph API
|
|
26
|
+
Explorer](https://developers.facebook.com/tools/explorer/) also works, but
|
|
27
|
+
those expire within hours unless they are exchanged for a long lived token
|
|
28
|
+
(see *Keeping the token alive* below).
|
|
29
|
+
|
|
30
|
+
## Setting up the module
|
|
31
|
+
|
|
32
|
+
Install the module, then open its configuration.
|
|
33
|
+
|
|
34
|
+
**Credentials**
|
|
35
|
+
|
|
36
|
+
| Setting | What it is for |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| Access token | The token from the steps above. Required. |
|
|
39
|
+
| App ID and App secret | Only needed if you want to refresh the token or check when it expires |
|
|
40
|
+
| Exchange for a long lived token | Swaps the token you pasted for one that lasts about 60 days. Leave this off for system user tokens, which already last forever. |
|
|
41
|
+
| Send app secret proof | Switch on if your Meta app is set to require proof of the app secret |
|
|
42
|
+
| API version | Which version of the Meta API to call. The default is current; change it only if Meta asks you to. |
|
|
43
|
+
| Maximum pages | A safety limit on how much data one request will read |
|
|
44
|
+
| Retries | How often to try again when Meta reports a temporary problem or a rate limit |
|
|
45
|
+
| Log requests | Writes every call to Meta into the server log, for troubleshooting |
|
|
46
|
+
|
|
47
|
+
**Ad account**
|
|
48
|
+
|
|
49
|
+
The second page lists the ad accounts your token can see. Pick the one you
|
|
50
|
+
work with most; it is used everywhere you do not name a different account.
|
|
51
|
+
|
|
52
|
+
## Tables
|
|
53
|
+
|
|
54
|
+
The module adds a table provider called **Meta ads**. Create a table, choose
|
|
55
|
+
*Meta ads* as the provider, and the table will show live data from Meta: no
|
|
56
|
+
copying, no synchronising, the rows are fetched when a view is opened.
|
|
57
|
+
|
|
58
|
+
First choose what the table should show:
|
|
59
|
+
|
|
60
|
+
- **Ad accounts** — the accounts your token can read
|
|
61
|
+
- **Campaigns**, **Ad sets**, **Ads**, **Ad creatives** — the contents of one
|
|
62
|
+
ad account
|
|
63
|
+
- **Insights** — performance figures: impressions, clicks, spend and so on
|
|
64
|
+
|
|
65
|
+
For insights you also choose the date range (either one of Meta's ready made
|
|
66
|
+
ranges such as *last_30d*, or your own From and To dates), the **level**
|
|
67
|
+
(one row per account, campaign, ad set or ad), and optionally a **time
|
|
68
|
+
increment** (`1` for a row per day, or `monthly`) and **breakdowns** such as
|
|
69
|
+
`age,gender` or `publisher_platform`.
|
|
70
|
+
|
|
71
|
+
On the second page the module shows you the rows it just read from Meta and
|
|
72
|
+
suggests a column for each field, with a sensible type. Remove any columns
|
|
73
|
+
you do not need, correct any types, and save. Those columns are what your
|
|
74
|
+
views will see.
|
|
75
|
+
|
|
76
|
+
Two settings are worth knowing about:
|
|
77
|
+
|
|
78
|
+
- **Cache for (seconds)** — how long rows already read from Meta are reused.
|
|
79
|
+
The default of 60 seconds keeps a busy list view from calling Meta on every
|
|
80
|
+
click. Set it to 0 to always read fresh data.
|
|
81
|
+
- **Maximum pages** — how many requests will be made before the table stops
|
|
82
|
+
asking for more. Raise it for large accounts, but expect views to be slower.
|
|
83
|
+
|
|
84
|
+
Tables of ad sets and ads are clever about relationships: when a view filters
|
|
85
|
+
on a campaign or ad set, only that campaign's or ad set's rows are fetched
|
|
86
|
+
from Meta rather than the whole account.
|
|
87
|
+
|
|
88
|
+
## Actions
|
|
89
|
+
|
|
90
|
+
**Meta sync** copies Meta objects into an ordinary Saltcorn table, rather
|
|
91
|
+
than reading them live. Use it when you want to keep history — Meta only
|
|
92
|
+
keeps performance figures for a limited time — or when you want data
|
|
93
|
+
available without waiting for Meta.
|
|
94
|
+
|
|
95
|
+
Choose the same things as for a table (object type, ad account, date range
|
|
96
|
+
for insights), then the destination table and which of its text fields holds
|
|
97
|
+
the Meta id. Rows are matched on that field, so running the action again
|
|
98
|
+
updates the rows it already created rather than duplicating them. Table
|
|
99
|
+
fields whose names match a Meta field are filled in automatically; anything
|
|
100
|
+
named differently can be mapped by hand. You can also store the whole
|
|
101
|
+
untouched object in a JSON field.
|
|
102
|
+
|
|
103
|
+
Tick *Delete missing rows* if the table should be an exact mirror, and
|
|
104
|
+
rows deleted at Meta should disappear from Saltcorn too. Point it at a
|
|
105
|
+
scheduled trigger — hourly or daily — to keep the copy up to date.
|
|
106
|
+
|
|
107
|
+
**Refresh Meta token** exchanges the stored access token for a fresh long
|
|
108
|
+
lived one and saves it. It needs the App ID and App secret to be set. If you
|
|
109
|
+
use an expiring token, run this from a monthly scheduled trigger so the
|
|
110
|
+
connection never goes stale. System user tokens do not need it.
|
|
111
|
+
|
|
112
|
+
## Functions
|
|
113
|
+
|
|
114
|
+
These can be used in code actions, calculated fields and formulas. Each one
|
|
115
|
+
returns exactly what Meta returned, and each takes an optional last argument
|
|
116
|
+
that overrides the module settings, so you can read a second ad account with
|
|
117
|
+
a different token.
|
|
118
|
+
|
|
119
|
+
| Function | What it returns |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| `get_meta_ad_accounts(query)` | The ad accounts your token can read |
|
|
122
|
+
| `get_meta_ad_account(accountId, query)` | One ad account |
|
|
123
|
+
| `get_meta_businesses(query)` | The businesses your token can read |
|
|
124
|
+
| `get_meta_business_ad_accounts(businessId, query)` | The ad accounts a business owns |
|
|
125
|
+
| `get_meta_campaigns(accountId, query)` | The campaigns in an ad account |
|
|
126
|
+
| `get_meta_campaign(campaignId, query)` | One campaign |
|
|
127
|
+
| `get_meta_adsets(accountId, query)` | The ad sets in an ad account |
|
|
128
|
+
| `get_meta_campaign_adsets(campaignId, query)` | The ad sets in a campaign |
|
|
129
|
+
| `get_meta_adset(adSetId, query)` | One ad set |
|
|
130
|
+
| `get_meta_ads(accountId, query)` | The ads in an ad account |
|
|
131
|
+
| `get_meta_campaign_ads(campaignId, query)` | The ads in a campaign |
|
|
132
|
+
| `get_meta_adset_ads(adSetId, query)` | The ads in an ad set |
|
|
133
|
+
| `get_meta_ad(adId, query)` | One ad |
|
|
134
|
+
| `get_meta_ad_creatives(accountId, query)` | The creatives in an ad account |
|
|
135
|
+
| `get_meta_ad_creative(creativeId, query)` | One creative |
|
|
136
|
+
| `get_meta_ad_preview(adId, adFormat)` | A ready made HTML preview of an ad |
|
|
137
|
+
| `get_meta_insights(objectId, query)` | Performance figures for an account, campaign, ad set or ad |
|
|
138
|
+
| `get_meta_insights_async(objectId, query)` | The same, run as a background report, for large date ranges |
|
|
139
|
+
| `get_meta_me(query)` | Who the token belongs to |
|
|
140
|
+
| `debug_meta_token(access_token)` | What a token is allowed to do and when it expires |
|
|
141
|
+
| `get_meta_long_lived_token(app_id, app_secret, access_token)` | A longer lasting version of a token |
|
|
142
|
+
| `meta_auth_fetch(path, query)` | Anything else: reads any Meta API address directly |
|
|
143
|
+
|
|
144
|
+
Leaving `accountId` or `objectId` empty uses the default ad account from the
|
|
145
|
+
module settings.
|
|
146
|
+
|
|
147
|
+
The `query` argument is optional and lets you say exactly what you want. For
|
|
148
|
+
example, the spend of every campaign over the last week:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
get_meta_insights("", {
|
|
152
|
+
level: "campaign",
|
|
153
|
+
date_preset: "last_7d",
|
|
154
|
+
fields: "campaign_name,impressions,clicks,spend"
|
|
155
|
+
})
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Or only the running ads, with their thumbnails:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
get_meta_ads("", {
|
|
162
|
+
effective_status: '["ACTIVE"]',
|
|
163
|
+
fields: "id,name,creative{thumbnail_url}"
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Things to know
|
|
168
|
+
|
|
169
|
+
- **Money is in cents.** Budgets, bids and amounts spent come from Meta as
|
|
170
|
+
whole numbers in the smallest unit of the account's currency: a daily
|
|
171
|
+
budget of `5000` means 50.00. Spend in performance figures is a decimal
|
|
172
|
+
number in the account's currency.
|
|
173
|
+
- **Meta limits how much you can read.** If you ask for a lot at once you may
|
|
174
|
+
see rate limit messages; the module waits and tries again a few times by
|
|
175
|
+
itself. Reading a large account is better done with the sync action on a
|
|
176
|
+
schedule than with a live table.
|
|
177
|
+
- **Deleted campaigns are hidden by default.** Set the *Statuses* option to
|
|
178
|
+
include `ARCHIVED` or `DELETED` if you need to see them.
|
|
179
|
+
- **Performance figures are not kept forever.** Meta only serves recent
|
|
180
|
+
history. Use the sync action if you want a permanent record.
|