@memberjunction/actions-bizapps-social 2.111.1 → 2.112.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +6 -6
- package/dist/base/base-social.action.d.ts.map +1 -1
- package/dist/base/base-social.action.js +18 -24
- package/dist/base/base-social.action.js.map +1 -1
- package/dist/providers/buffer/buffer-base.action.d.ts.map +1 -1
- package/dist/providers/buffer/buffer-base.action.js +35 -34
- package/dist/providers/buffer/buffer-base.action.js.map +1 -1
- package/dist/providers/facebook/actions/boost-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/boost-post.action.js +33 -33
- package/dist/providers/facebook/actions/boost-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/create-album.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/create-album.action.js +34 -36
- package/dist/providers/facebook/actions/create-album.action.js.map +1 -1
- package/dist/providers/facebook/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/create-post.action.js +20 -20
- package/dist/providers/facebook/actions/create-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-page-insights.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-page-insights.action.js +25 -27
- package/dist/providers/facebook/actions/get-page-insights.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-page-posts.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-page-posts.action.js +19 -23
- package/dist/providers/facebook/actions/get-page-posts.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-post-insights.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-post-insights.action.js +28 -32
- package/dist/providers/facebook/actions/get-post-insights.action.js.map +1 -1
- package/dist/providers/facebook/actions/respond-to-comments.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/respond-to-comments.action.js +42 -44
- package/dist/providers/facebook/actions/respond-to-comments.action.js.map +1 -1
- package/dist/providers/facebook/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/schedule-post.action.js +29 -29
- package/dist/providers/facebook/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/search-posts.action.js +37 -39
- package/dist/providers/facebook/actions/search-posts.action.js.map +1 -1
- package/dist/providers/facebook/facebook-base.action.d.ts.map +1 -1
- package/dist/providers/facebook/facebook-base.action.js +44 -59
- package/dist/providers/facebook/facebook-base.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js +33 -31
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js +28 -32
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js +19 -19
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-analytics.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-analytics.action.js +24 -26
- package/dist/providers/hootsuite/actions/get-analytics.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js +22 -22
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-social-profiles.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js +32 -34
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/search-posts.action.js +43 -52
- package/dist/providers/hootsuite/actions/search-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js +30 -28
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/hootsuite-base.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/hootsuite-base.action.js +18 -20
- package/dist/providers/hootsuite/hootsuite-base.action.js.map +1 -1
- package/dist/providers/instagram/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/create-post.action.js +27 -26
- package/dist/providers/instagram/actions/create-post.action.js.map +1 -1
- package/dist/providers/instagram/actions/create-story.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/create-story.action.js +35 -35
- package/dist/providers/instagram/actions/create-story.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-account-insights.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-account-insights.action.js +38 -59
- package/dist/providers/instagram/actions/get-account-insights.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-business-posts.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-business-posts.action.js +29 -29
- package/dist/providers/instagram/actions/get-business-posts.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-comments.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-comments.action.js +36 -36
- package/dist/providers/instagram/actions/get-comments.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-post-insights.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-post-insights.action.js +23 -25
- package/dist/providers/instagram/actions/get-post-insights.action.js.map +1 -1
- package/dist/providers/instagram/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/schedule-post.action.js +25 -25
- package/dist/providers/instagram/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/instagram/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/search-posts.action.js +56 -60
- package/dist/providers/instagram/actions/search-posts.action.js.map +1 -1
- package/dist/providers/instagram/instagram-base.action.d.ts.map +1 -1
- package/dist/providers/instagram/instagram-base.action.js +25 -27
- package/dist/providers/instagram/instagram-base.action.js.map +1 -1
- package/dist/providers/linkedin/actions/create-article.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/create-article.action.js +55 -45
- package/dist/providers/linkedin/actions/create-article.action.js.map +1 -1
- package/dist/providers/linkedin/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/create-post.action.js +31 -29
- package/dist/providers/linkedin/actions/create-post.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-followers.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-followers.action.js +28 -28
- package/dist/providers/linkedin/actions/get-followers.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-organization-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-organization-posts.action.js +20 -20
- package/dist/providers/linkedin/actions/get-organization-posts.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-personal-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-personal-posts.action.js +19 -19
- package/dist/providers/linkedin/actions/get-personal-posts.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-post-analytics.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-post-analytics.action.js +25 -23
- package/dist/providers/linkedin/actions/get-post-analytics.action.js.map +1 -1
- package/dist/providers/linkedin/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/schedule-post.action.js +32 -30
- package/dist/providers/linkedin/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/linkedin/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/search-posts.action.js +28 -30
- package/dist/providers/linkedin/actions/search-posts.action.js.map +1 -1
- package/dist/providers/linkedin/linkedin-base.action.d.ts.map +1 -1
- package/dist/providers/linkedin/linkedin-base.action.js +33 -38
- package/dist/providers/linkedin/linkedin-base.action.js.map +1 -1
- package/dist/providers/tiktok/tiktok-base.action.d.ts.map +1 -1
- package/dist/providers/tiktok/tiktok-base.action.js +25 -26
- package/dist/providers/tiktok/tiktok-base.action.js.map +1 -1
- package/dist/providers/twitter/actions/create-thread.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/create-thread.action.js +25 -29
- package/dist/providers/twitter/actions/create-thread.action.js.map +1 -1
- package/dist/providers/twitter/actions/create-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/create-tweet.action.js +23 -23
- package/dist/providers/twitter/actions/create-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/delete-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/delete-tweet.action.js +19 -19
- package/dist/providers/twitter/actions/delete-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-analytics.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-analytics.action.js +40 -47
- package/dist/providers/twitter/actions/get-analytics.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-mentions.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-mentions.action.js +30 -31
- package/dist/providers/twitter/actions/get-mentions.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-timeline.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-timeline.action.js +29 -29
- package/dist/providers/twitter/actions/get-timeline.action.js.map +1 -1
- package/dist/providers/twitter/actions/schedule-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/schedule-tweet.action.js +26 -26
- package/dist/providers/twitter/actions/schedule-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/search-tweets.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/search-tweets.action.js +56 -58
- package/dist/providers/twitter/actions/search-tweets.action.js.map +1 -1
- package/dist/providers/twitter/twitter-base.action.d.ts.map +1 -1
- package/dist/providers/twitter/twitter-base.action.js +58 -68
- package/dist/providers/twitter/twitter-base.action.js.map +1 -1
- package/dist/providers/youtube/youtube-base.action.d.ts +1 -1
- package/dist/providers/youtube/youtube-base.action.d.ts.map +1 -1
- package/dist/providers/youtube/youtube-base.action.js +22 -25
- package/dist/providers/youtube/youtube-base.action.js.map +1 -1
- package/package.json +5 -6
- package/src/base/base-social.action.ts +217 -224
- package/src/providers/buffer/buffer-base.action.ts +435 -441
- package/src/providers/facebook/actions/boost-post.action.ts +350 -386
- package/src/providers/facebook/actions/create-album.action.ts +291 -307
- package/src/providers/facebook/actions/create-post.action.ts +224 -227
- package/src/providers/facebook/actions/get-page-insights.action.ts +383 -403
- package/src/providers/facebook/actions/get-page-posts.action.ts +214 -225
- package/src/providers/facebook/actions/get-post-insights.action.ts +300 -316
- package/src/providers/facebook/actions/respond-to-comments.action.ts +319 -336
- package/src/providers/facebook/actions/schedule-post.action.ts +289 -292
- package/src/providers/facebook/actions/search-posts.action.ts +399 -413
- package/src/providers/facebook/facebook-base.action.ts +653 -670
- package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
- package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +184 -189
- package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +160 -161
- package/src/providers/hootsuite/actions/get-analytics.action.ts +249 -254
- package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +206 -207
- package/src/providers/hootsuite/actions/get-social-profiles.action.ts +206 -205
- package/src/providers/hootsuite/actions/search-posts.action.ts +351 -369
- package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +211 -209
- package/src/providers/hootsuite/hootsuite-base.action.ts +301 -307
- package/src/providers/instagram/actions/create-post.action.ts +276 -296
- package/src/providers/instagram/actions/create-story.action.ts +378 -394
- package/src/providers/instagram/actions/get-account-insights.action.ts +384 -420
- package/src/providers/instagram/actions/get-business-posts.action.ts +233 -242
- package/src/providers/instagram/actions/get-comments.action.ts +365 -377
- package/src/providers/instagram/actions/get-post-insights.action.ts +265 -273
- package/src/providers/instagram/actions/schedule-post.action.ts +233 -235
- package/src/providers/instagram/actions/search-posts.action.ts +512 -538
- package/src/providers/instagram/instagram-base.action.ts +368 -393
- package/src/providers/linkedin/actions/create-article.action.ts +275 -266
- package/src/providers/linkedin/actions/create-post.action.ts +179 -177
- package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
- package/src/providers/linkedin/actions/get-organization-posts.action.ts +146 -147
- package/src/providers/linkedin/actions/get-personal-posts.action.ts +138 -139
- package/src/providers/linkedin/actions/get-post-analytics.action.ts +190 -189
- package/src/providers/linkedin/actions/schedule-post.action.ts +191 -189
- package/src/providers/linkedin/actions/search-posts.action.ts +275 -283
- package/src/providers/linkedin/linkedin-base.action.ts +407 -421
- package/src/providers/tiktok/tiktok-base.action.ts +305 -320
- package/src/providers/twitter/actions/create-thread.action.ts +203 -207
- package/src/providers/twitter/actions/create-tweet.action.ts +187 -188
- package/src/providers/twitter/actions/delete-tweet.action.ts +128 -129
- package/src/providers/twitter/actions/get-analytics.action.ts +402 -411
- package/src/providers/twitter/actions/get-mentions.action.ts +218 -219
- package/src/providers/twitter/actions/get-timeline.action.ts +232 -233
- package/src/providers/twitter/actions/schedule-tweet.action.ts +221 -222
- package/src/providers/twitter/actions/search-tweets.action.ts +540 -543
- package/src/providers/twitter/twitter-base.action.ts +541 -560
- package/src/providers/youtube/youtube-base.action.ts +320 -333
|
@@ -2,7 +2,7 @@ import { RegisterClass } from '@memberjunction/global';
|
|
|
2
2
|
import { FacebookBaseAction } from '../facebook-base.action';
|
|
3
3
|
import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
|
|
4
4
|
import { SocialMediaErrorCode } from '../../../base/base-social.action';
|
|
5
|
-
import { LogStatus, LogError } from '@memberjunction/
|
|
5
|
+
import { LogStatus, LogError } from '@memberjunction/global';
|
|
6
6
|
import axios from 'axios';
|
|
7
7
|
import { BaseAction } from '@memberjunction/actions';
|
|
8
8
|
|
|
@@ -12,402 +12,366 @@ import { BaseAction } from '@memberjunction/actions';
|
|
|
12
12
|
*/
|
|
13
13
|
@RegisterClass(BaseAction, 'FacebookBoostPostAction')
|
|
14
14
|
export class FacebookBoostPostAction extends FacebookBaseAction {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (!postId) {
|
|
98
|
-
return {
|
|
99
|
-
Success: false,
|
|
100
|
-
Message: 'PostID is required',
|
|
101
|
-
ResultCode: 'MISSING_REQUIRED_PARAM'
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (!adAccountId) {
|
|
106
|
-
return {
|
|
107
|
-
Success: false,
|
|
108
|
-
Message: 'AdAccountID is required',
|
|
109
|
-
ResultCode: 'MISSING_REQUIRED_PARAM'
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (!budget || budget <= 0) {
|
|
114
|
-
return {
|
|
115
|
-
Success: false,
|
|
116
|
-
Message: 'Budget must be a positive number',
|
|
117
|
-
ResultCode: 'INVALID_BUDGET'
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Initialize OAuth
|
|
122
|
-
if (!await this.initializeOAuth(companyIntegrationId)) {
|
|
123
|
-
return {
|
|
124
|
-
Success: false,
|
|
125
|
-
Message: 'Failed to initialize Facebook OAuth connection',
|
|
126
|
-
ResultCode: 'INVALID_TOKEN'
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Get parameters
|
|
131
|
-
const duration = this.getParamValue(Params, 'Duration') as number || 7;
|
|
132
|
-
const objective = this.getParamValue(Params, 'Objective') as string || 'POST_ENGAGEMENT';
|
|
133
|
-
const audienceType = this.getParamValue(Params, 'AudienceType') as string || 'AUTO';
|
|
134
|
-
const targetingSpec = this.getParamValue(Params, 'TargetingSpec') as any;
|
|
135
|
-
const startTime = this.getParamValue(Params, 'StartTime') as string;
|
|
136
|
-
const callToAction = this.getParamValue(Params, 'CallToAction') as string;
|
|
137
|
-
|
|
138
|
-
// Validate duration
|
|
139
|
-
if (duration < 1 || duration > 30) {
|
|
140
|
-
return {
|
|
141
|
-
Success: false,
|
|
142
|
-
Message: 'Duration must be between 1 and 30 days',
|
|
143
|
-
ResultCode: 'INVALID_DURATION'
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Extract page ID from post ID
|
|
148
|
-
const pageId = postId.split('_')[0];
|
|
149
|
-
|
|
150
|
-
// Get page access token
|
|
151
|
-
const pageToken = await this.getPageAccessToken(pageId);
|
|
152
|
-
|
|
153
|
-
LogStatus(`Creating boost campaign for post ${postId}...`);
|
|
154
|
-
|
|
155
|
-
// Step 1: Create campaign
|
|
156
|
-
const campaignName = `Boost Post ${postId} - ${new Date().toISOString()}`;
|
|
157
|
-
const campaign = await this.createCampaign(adAccountId, campaignName, objective);
|
|
158
|
-
|
|
159
|
-
// Step 2: Create ad set with targeting
|
|
160
|
-
const adSetName = `Ad Set for ${postId}`;
|
|
161
|
-
const targeting = this.buildTargeting(audienceType, targetingSpec, pageId);
|
|
162
|
-
const adSet = await this.createAdSet(
|
|
163
|
-
adAccountId,
|
|
164
|
-
campaign.id,
|
|
165
|
-
adSetName,
|
|
166
|
-
budget,
|
|
167
|
-
duration,
|
|
168
|
-
targeting,
|
|
169
|
-
startTime
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
// Step 3: Create ad creative from post
|
|
173
|
-
const creative = await this.createCreativeFromPost(adAccountId, postId, pageToken, callToAction);
|
|
174
|
-
|
|
175
|
-
// Step 4: Create the ad
|
|
176
|
-
const adName = `Boosted Post ${postId}`;
|
|
177
|
-
const ad = await this.createAd(adAccountId, adSet.id, creative.id, adName);
|
|
178
|
-
|
|
179
|
-
// Get boost summary
|
|
180
|
-
const boostSummary = {
|
|
181
|
-
campaignId: campaign.id,
|
|
182
|
-
adSetId: adSet.id,
|
|
183
|
-
adId: ad.id,
|
|
184
|
-
creativeId: creative.id,
|
|
185
|
-
postId,
|
|
186
|
-
budget,
|
|
187
|
-
duration,
|
|
188
|
-
objective,
|
|
189
|
-
audienceType,
|
|
190
|
-
startTime: adSet.start_time,
|
|
191
|
-
endTime: adSet.end_time,
|
|
192
|
-
status: ad.status,
|
|
193
|
-
reviewStatus: ad.review_feedback?.global_review_status || 'PENDING',
|
|
194
|
-
previewUrl: `https://www.facebook.com/ads/manager/account/campaigns?act=${adAccountId}&selected_campaign_ids=${campaign.id}`
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
LogStatus(`Successfully created boost campaign for post ${postId}`);
|
|
198
|
-
|
|
199
|
-
return {
|
|
200
|
-
Success: true,
|
|
201
|
-
Message: 'Post boost created successfully',
|
|
202
|
-
ResultCode: 'SUCCESS',
|
|
203
|
-
Params
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
} catch (error) {
|
|
207
|
-
LogError(`Failed to boost Facebook post: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
208
|
-
|
|
209
|
-
if (this.isAuthError(error)) {
|
|
210
|
-
return this.handleOAuthError(error);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Check for specific ad-related errors
|
|
214
|
-
if (error instanceof Error) {
|
|
215
|
-
if (error.message.includes('permissions')) {
|
|
216
|
-
return {
|
|
217
|
-
Success: false,
|
|
218
|
-
Message: 'Insufficient permissions. Ensure the token has ads_management permission.',
|
|
219
|
-
ResultCode: 'INSUFFICIENT_PERMISSIONS'
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
if (error.message.includes('budget')) {
|
|
223
|
-
return {
|
|
224
|
-
Success: false,
|
|
225
|
-
Message: 'Invalid budget. Check minimum budget requirements for your currency.',
|
|
226
|
-
ResultCode: 'INVALID_BUDGET'
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return {
|
|
232
|
-
Success: false,
|
|
233
|
-
Message: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
234
|
-
ResultCode: 'ERROR'
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Create a campaign
|
|
241
|
-
*/
|
|
242
|
-
private async createCampaign(adAccountId: string, name: string, objective: string): Promise<any> {
|
|
243
|
-
const response = await this.axiosInstance.post(
|
|
244
|
-
`/${adAccountId}/campaigns`,
|
|
245
|
-
{
|
|
246
|
-
name,
|
|
247
|
-
objective,
|
|
248
|
-
status: 'PAUSED', // Start paused for safety
|
|
249
|
-
special_ad_categories: [] // Required field
|
|
250
|
-
}
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
return response.data;
|
|
254
|
-
}
|
|
15
|
+
/**
|
|
16
|
+
* Get action description
|
|
17
|
+
*/
|
|
18
|
+
public get Description(): string {
|
|
19
|
+
return 'Boosts (promotes) a Facebook post to reach a wider audience through paid advertising';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Define the parameters for this action
|
|
24
|
+
*/
|
|
25
|
+
public get Params(): ActionParam[] {
|
|
26
|
+
return [
|
|
27
|
+
...this.commonSocialParams,
|
|
28
|
+
{
|
|
29
|
+
Name: 'PostID',
|
|
30
|
+
Type: 'Input',
|
|
31
|
+
Value: null,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
Name: 'AdAccountID',
|
|
35
|
+
Type: 'Input',
|
|
36
|
+
Value: null,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
Name: 'Budget',
|
|
40
|
+
Type: 'Input',
|
|
41
|
+
Value: null,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
Name: 'Duration',
|
|
45
|
+
Type: 'Input',
|
|
46
|
+
Value: 7,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
Name: 'Objective',
|
|
50
|
+
Type: 'Input',
|
|
51
|
+
Value: 'POST_ENGAGEMENT',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
Name: 'AudienceType',
|
|
55
|
+
Type: 'Input',
|
|
56
|
+
Value: 'AUTO',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
Name: 'TargetingSpec',
|
|
60
|
+
Type: 'Input',
|
|
61
|
+
Value: null,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
Name: 'StartTime',
|
|
65
|
+
Type: 'Input',
|
|
66
|
+
Value: null,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
Name: 'CallToAction',
|
|
70
|
+
Type: 'Input',
|
|
71
|
+
Value: null,
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Execute the action
|
|
78
|
+
*/
|
|
79
|
+
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
|
|
80
|
+
const { Params, ContextUser } = params;
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// Validate required parameters
|
|
84
|
+
const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
|
|
85
|
+
const postId = this.getParamValue(Params, 'PostID');
|
|
86
|
+
const adAccountId = this.getParamValue(Params, 'AdAccountID');
|
|
87
|
+
const budget = this.getParamValue(Params, 'Budget') as number;
|
|
88
|
+
|
|
89
|
+
if (!companyIntegrationId) {
|
|
90
|
+
return {
|
|
91
|
+
Success: false,
|
|
92
|
+
Message: 'CompanyIntegrationID is required',
|
|
93
|
+
ResultCode: 'INVALID_TOKEN',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
255
96
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
budget: number,
|
|
264
|
-
durationDays: number,
|
|
265
|
-
targeting: any,
|
|
266
|
-
startTime?: string
|
|
267
|
-
): Promise<any> {
|
|
268
|
-
const now = new Date();
|
|
269
|
-
const start = startTime ? new Date(startTime) : now;
|
|
270
|
-
const end = new Date(start);
|
|
271
|
-
end.setDate(end.getDate() + durationDays);
|
|
272
|
-
|
|
273
|
-
// Calculate daily budget
|
|
274
|
-
const dailyBudget = Math.ceil((budget * 100) / durationDays); // Convert to cents
|
|
275
|
-
|
|
276
|
-
const response = await this.axiosInstance.post(
|
|
277
|
-
`/${adAccountId}/adsets`,
|
|
278
|
-
{
|
|
279
|
-
name,
|
|
280
|
-
campaign_id: campaignId,
|
|
281
|
-
daily_budget: dailyBudget,
|
|
282
|
-
billing_event: 'IMPRESSIONS',
|
|
283
|
-
optimization_goal: this.getOptimizationGoal(campaignId),
|
|
284
|
-
bid_strategy: 'LOWEST_COST_WITHOUT_CAP',
|
|
285
|
-
targeting,
|
|
286
|
-
start_time: start.toISOString(),
|
|
287
|
-
end_time: end.toISOString(),
|
|
288
|
-
status: 'PAUSED'
|
|
289
|
-
}
|
|
290
|
-
);
|
|
291
|
-
|
|
292
|
-
return response.data;
|
|
293
|
-
}
|
|
97
|
+
if (!postId) {
|
|
98
|
+
return {
|
|
99
|
+
Success: false,
|
|
100
|
+
Message: 'PostID is required',
|
|
101
|
+
ResultCode: 'MISSING_REQUIRED_PARAM',
|
|
102
|
+
};
|
|
103
|
+
}
|
|
294
104
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
postId: string,
|
|
301
|
-
pageToken: string,
|
|
302
|
-
callToAction?: string
|
|
303
|
-
): Promise<any> {
|
|
304
|
-
const creativeData: any = {
|
|
305
|
-
name: `Creative for ${postId}`,
|
|
306
|
-
object_story_id: postId
|
|
105
|
+
if (!adAccountId) {
|
|
106
|
+
return {
|
|
107
|
+
Success: false,
|
|
108
|
+
Message: 'AdAccountID is required',
|
|
109
|
+
ResultCode: 'MISSING_REQUIRED_PARAM',
|
|
307
110
|
};
|
|
111
|
+
}
|
|
308
112
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
113
|
+
if (!budget || budget <= 0) {
|
|
114
|
+
return {
|
|
115
|
+
Success: false,
|
|
116
|
+
Message: 'Budget must be a positive number',
|
|
117
|
+
ResultCode: 'INVALID_BUDGET',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Initialize OAuth
|
|
122
|
+
if (!(await this.initializeOAuth(companyIntegrationId))) {
|
|
123
|
+
return {
|
|
124
|
+
Success: false,
|
|
125
|
+
Message: 'Failed to initialize Facebook OAuth connection',
|
|
126
|
+
ResultCode: 'INVALID_TOKEN',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Get parameters
|
|
131
|
+
const duration = (this.getParamValue(Params, 'Duration') as number) || 7;
|
|
132
|
+
const objective = (this.getParamValue(Params, 'Objective') as string) || 'POST_ENGAGEMENT';
|
|
133
|
+
const audienceType = (this.getParamValue(Params, 'AudienceType') as string) || 'AUTO';
|
|
134
|
+
const targetingSpec = this.getParamValue(Params, 'TargetingSpec') as any;
|
|
135
|
+
const startTime = this.getParamValue(Params, 'StartTime') as string;
|
|
136
|
+
const callToAction = this.getParamValue(Params, 'CallToAction') as string;
|
|
137
|
+
|
|
138
|
+
// Validate duration
|
|
139
|
+
if (duration < 1 || duration > 30) {
|
|
140
|
+
return {
|
|
141
|
+
Success: false,
|
|
142
|
+
Message: 'Duration must be between 1 and 30 days',
|
|
143
|
+
ResultCode: 'INVALID_DURATION',
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Extract page ID from post ID
|
|
148
|
+
const pageId = postId.split('_')[0];
|
|
149
|
+
|
|
150
|
+
// Get page access token
|
|
151
|
+
const pageToken = await this.getPageAccessToken(pageId);
|
|
152
|
+
|
|
153
|
+
LogStatus(`Creating boost campaign for post ${postId}...`);
|
|
154
|
+
|
|
155
|
+
// Step 1: Create campaign
|
|
156
|
+
const campaignName = `Boost Post ${postId} - ${new Date().toISOString()}`;
|
|
157
|
+
const campaign = await this.createCampaign(adAccountId, campaignName, objective);
|
|
158
|
+
|
|
159
|
+
// Step 2: Create ad set with targeting
|
|
160
|
+
const adSetName = `Ad Set for ${postId}`;
|
|
161
|
+
const targeting = this.buildTargeting(audienceType, targetingSpec, pageId);
|
|
162
|
+
const adSet = await this.createAdSet(adAccountId, campaign.id, adSetName, budget, duration, targeting, startTime);
|
|
163
|
+
|
|
164
|
+
// Step 3: Create ad creative from post
|
|
165
|
+
const creative = await this.createCreativeFromPost(adAccountId, postId, pageToken, callToAction);
|
|
166
|
+
|
|
167
|
+
// Step 4: Create the ad
|
|
168
|
+
const adName = `Boosted Post ${postId}`;
|
|
169
|
+
const ad = await this.createAd(adAccountId, adSet.id, creative.id, adName);
|
|
170
|
+
|
|
171
|
+
// Get boost summary
|
|
172
|
+
const boostSummary = {
|
|
173
|
+
campaignId: campaign.id,
|
|
174
|
+
adSetId: adSet.id,
|
|
175
|
+
adId: ad.id,
|
|
176
|
+
creativeId: creative.id,
|
|
177
|
+
postId,
|
|
178
|
+
budget,
|
|
179
|
+
duration,
|
|
180
|
+
objective,
|
|
181
|
+
audienceType,
|
|
182
|
+
startTime: adSet.start_time,
|
|
183
|
+
endTime: adSet.end_time,
|
|
184
|
+
status: ad.status,
|
|
185
|
+
reviewStatus: ad.review_feedback?.global_review_status || 'PENDING',
|
|
186
|
+
previewUrl: `https://www.facebook.com/ads/manager/account/campaigns?act=${adAccountId}&selected_campaign_ids=${campaign.id}`,
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
LogStatus(`Successfully created boost campaign for post ${postId}`);
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
Success: true,
|
|
193
|
+
Message: 'Post boost created successfully',
|
|
194
|
+
ResultCode: 'SUCCESS',
|
|
195
|
+
Params,
|
|
196
|
+
};
|
|
197
|
+
} catch (error) {
|
|
198
|
+
LogError(`Failed to boost Facebook post: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
199
|
+
|
|
200
|
+
if (this.isAuthError(error)) {
|
|
201
|
+
return this.handleOAuthError(error);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Check for specific ad-related errors
|
|
205
|
+
if (error instanceof Error) {
|
|
206
|
+
if (error.message.includes('permissions')) {
|
|
207
|
+
return {
|
|
208
|
+
Success: false,
|
|
209
|
+
Message: 'Insufficient permissions. Ensure the token has ads_management permission.',
|
|
210
|
+
ResultCode: 'INSUFFICIENT_PERMISSIONS',
|
|
211
|
+
};
|
|
327
212
|
}
|
|
213
|
+
if (error.message.includes('budget')) {
|
|
214
|
+
return {
|
|
215
|
+
Success: false,
|
|
216
|
+
Message: 'Invalid budget. Check minimum budget requirements for your currency.',
|
|
217
|
+
ResultCode: 'INVALID_BUDGET',
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
328
221
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
return response.data;
|
|
222
|
+
return {
|
|
223
|
+
Success: false,
|
|
224
|
+
Message: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
225
|
+
ResultCode: 'ERROR',
|
|
226
|
+
};
|
|
335
227
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Create a campaign
|
|
232
|
+
*/
|
|
233
|
+
private async createCampaign(adAccountId: string, name: string, objective: string): Promise<any> {
|
|
234
|
+
const response = await this.axiosInstance.post(`/${adAccountId}/campaigns`, {
|
|
235
|
+
name,
|
|
236
|
+
objective,
|
|
237
|
+
status: 'PAUSED', // Start paused for safety
|
|
238
|
+
special_ad_categories: [], // Required field
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
return response.data;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Create an ad set
|
|
246
|
+
*/
|
|
247
|
+
private async createAdSet(
|
|
248
|
+
adAccountId: string,
|
|
249
|
+
campaignId: string,
|
|
250
|
+
name: string,
|
|
251
|
+
budget: number,
|
|
252
|
+
durationDays: number,
|
|
253
|
+
targeting: any,
|
|
254
|
+
startTime?: string
|
|
255
|
+
): Promise<any> {
|
|
256
|
+
const now = new Date();
|
|
257
|
+
const start = startTime ? new Date(startTime) : now;
|
|
258
|
+
const end = new Date(start);
|
|
259
|
+
end.setDate(end.getDate() + durationDays);
|
|
260
|
+
|
|
261
|
+
// Calculate daily budget
|
|
262
|
+
const dailyBudget = Math.ceil((budget * 100) / durationDays); // Convert to cents
|
|
263
|
+
|
|
264
|
+
const response = await this.axiosInstance.post(`/${adAccountId}/adsets`, {
|
|
265
|
+
name,
|
|
266
|
+
campaign_id: campaignId,
|
|
267
|
+
daily_budget: dailyBudget,
|
|
268
|
+
billing_event: 'IMPRESSIONS',
|
|
269
|
+
optimization_goal: this.getOptimizationGoal(campaignId),
|
|
270
|
+
bid_strategy: 'LOWEST_COST_WITHOUT_CAP',
|
|
271
|
+
targeting,
|
|
272
|
+
start_time: start.toISOString(),
|
|
273
|
+
end_time: end.toISOString(),
|
|
274
|
+
status: 'PAUSED',
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
return response.data;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Create creative from existing post
|
|
282
|
+
*/
|
|
283
|
+
private async createCreativeFromPost(adAccountId: string, postId: string, pageToken: string, callToAction?: string): Promise<any> {
|
|
284
|
+
const creativeData: any = {
|
|
285
|
+
name: `Creative for ${postId}`,
|
|
286
|
+
object_story_id: postId,
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
if (callToAction) {
|
|
290
|
+
// Get post details to add CTA
|
|
291
|
+
const postResponse = await axios.get(`${this.apiBaseUrl}/${postId}`, {
|
|
292
|
+
params: {
|
|
293
|
+
access_token: pageToken,
|
|
294
|
+
fields: 'permalink_url',
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
creativeData.call_to_action = {
|
|
299
|
+
type: callToAction,
|
|
300
|
+
value: {
|
|
301
|
+
link: postResponse.data.permalink_url,
|
|
302
|
+
},
|
|
303
|
+
};
|
|
357
304
|
}
|
|
358
305
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
306
|
+
const response = await this.axiosInstance.post(`/${adAccountId}/adcreatives`, creativeData);
|
|
307
|
+
|
|
308
|
+
return response.data;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Create the ad
|
|
313
|
+
*/
|
|
314
|
+
private async createAd(adAccountId: string, adSetId: string, creativeId: string, name: string): Promise<any> {
|
|
315
|
+
const response = await this.axiosInstance.post(`/${adAccountId}/ads`, {
|
|
316
|
+
name,
|
|
317
|
+
adset_id: adSetId,
|
|
318
|
+
creative: { creative_id: creativeId },
|
|
319
|
+
status: 'PAUSED',
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
return response.data;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Build targeting specification
|
|
327
|
+
*/
|
|
328
|
+
private buildTargeting(audienceType: string, customTargeting: any, pageId: string): any {
|
|
329
|
+
const baseTargeting: any = {
|
|
330
|
+
geo_locations: {
|
|
331
|
+
countries: ['US'], // Default to US, can be overridden
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
switch (audienceType) {
|
|
336
|
+
case 'FANS':
|
|
337
|
+
baseTargeting.connections = [pageId];
|
|
338
|
+
break;
|
|
339
|
+
case 'FANS_AND_CONNECTIONS':
|
|
340
|
+
baseTargeting.connections = [pageId];
|
|
341
|
+
baseTargeting.friends_of_connections = [pageId];
|
|
342
|
+
break;
|
|
343
|
+
case 'CUSTOM':
|
|
344
|
+
if (customTargeting) {
|
|
345
|
+
return { ...baseTargeting, ...customTargeting };
|
|
386
346
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
return baseTargeting;
|
|
347
|
+
break;
|
|
348
|
+
case 'AUTO':
|
|
349
|
+
default:
|
|
350
|
+
// Facebook will automatically optimize targeting
|
|
351
|
+
break;
|
|
394
352
|
}
|
|
395
353
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
private getOptimizationGoal(objective: string): string {
|
|
400
|
-
const goalMap: Record<string, string> = {
|
|
401
|
-
'POST_ENGAGEMENT': 'POST_ENGAGEMENT',
|
|
402
|
-
'REACH': 'REACH',
|
|
403
|
-
'LINK_CLICKS': 'LINK_CLICKS',
|
|
404
|
-
'PAGE_LIKES': 'PAGE_LIKES',
|
|
405
|
-
'BRAND_AWARENESS': 'AD_RECALL_LIFT',
|
|
406
|
-
'VIDEO_VIEWS': 'VIDEO_VIEWS'
|
|
407
|
-
};
|
|
408
|
-
|
|
409
|
-
return goalMap[objective] || 'POST_ENGAGEMENT';
|
|
354
|
+
// Add any custom targeting on top
|
|
355
|
+
if (customTargeting && audienceType !== 'CUSTOM') {
|
|
356
|
+
Object.assign(baseTargeting, customTargeting);
|
|
410
357
|
}
|
|
411
358
|
|
|
412
|
-
|
|
413
|
-
}
|
|
359
|
+
return baseTargeting;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Get optimization goal based on objective
|
|
364
|
+
*/
|
|
365
|
+
private getOptimizationGoal(objective: string): string {
|
|
366
|
+
const goalMap: Record<string, string> = {
|
|
367
|
+
POST_ENGAGEMENT: 'POST_ENGAGEMENT',
|
|
368
|
+
REACH: 'REACH',
|
|
369
|
+
LINK_CLICKS: 'LINK_CLICKS',
|
|
370
|
+
PAGE_LIKES: 'PAGE_LIKES',
|
|
371
|
+
BRAND_AWARENESS: 'AD_RECALL_LIFT',
|
|
372
|
+
VIDEO_VIEWS: 'VIDEO_VIEWS',
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
return goalMap[objective] || 'POST_ENGAGEMENT';
|
|
376
|
+
}
|
|
377
|
+
}
|