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