@memberjunction/actions-bizapps-social 2.112.0 → 2.113.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 +13 -0
- package/dist/base/base-social.action.d.ts.map +1 -1
- package/dist/base/base-social.action.js +24 -18
- 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 +34 -35
- 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 +36 -34
- 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 +27 -25
- 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 +23 -19
- 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 +32 -28
- 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 +44 -42
- 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 +39 -37
- 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 +59 -44
- 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 +31 -33
- 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 +32 -28
- 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 +26 -24
- 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 +34 -32
- 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 +52 -43
- 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 +28 -30
- 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 +20 -18
- 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 +26 -27
- 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 +59 -38
- 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 +25 -23
- 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 +60 -56
- 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 +27 -25
- 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 +45 -55
- 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 +29 -31
- 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 +23 -25
- 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 +30 -32
- 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 +30 -28
- 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 +38 -33
- 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 +26 -25
- 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 +29 -25
- 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 +47 -40
- 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 +31 -30
- 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 +58 -56
- 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 +68 -58
- 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 +25 -22
- package/dist/providers/youtube/youtube-base.action.js.map +1 -1
- package/package.json +6 -5
- package/src/base/base-social.action.ts +224 -217
- package/src/providers/buffer/buffer-base.action.ts +441 -435
- package/src/providers/facebook/actions/boost-post.action.ts +386 -350
- package/src/providers/facebook/actions/create-album.action.ts +307 -291
- package/src/providers/facebook/actions/create-post.action.ts +227 -224
- package/src/providers/facebook/actions/get-page-insights.action.ts +403 -383
- package/src/providers/facebook/actions/get-page-posts.action.ts +225 -214
- package/src/providers/facebook/actions/get-post-insights.action.ts +316 -300
- package/src/providers/facebook/actions/respond-to-comments.action.ts +336 -319
- package/src/providers/facebook/actions/schedule-post.action.ts +292 -289
- package/src/providers/facebook/actions/search-posts.action.ts +413 -399
- package/src/providers/facebook/facebook-base.action.ts +670 -653
- package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
- package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +189 -184
- package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +161 -160
- package/src/providers/hootsuite/actions/get-analytics.action.ts +254 -249
- package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +207 -206
- package/src/providers/hootsuite/actions/get-social-profiles.action.ts +205 -206
- package/src/providers/hootsuite/actions/search-posts.action.ts +369 -351
- package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +209 -211
- package/src/providers/hootsuite/hootsuite-base.action.ts +307 -301
- package/src/providers/instagram/actions/create-post.action.ts +296 -276
- package/src/providers/instagram/actions/create-story.action.ts +394 -378
- package/src/providers/instagram/actions/get-account-insights.action.ts +420 -384
- package/src/providers/instagram/actions/get-business-posts.action.ts +242 -233
- package/src/providers/instagram/actions/get-comments.action.ts +377 -365
- package/src/providers/instagram/actions/get-post-insights.action.ts +273 -265
- package/src/providers/instagram/actions/schedule-post.action.ts +235 -233
- package/src/providers/instagram/actions/search-posts.action.ts +538 -512
- package/src/providers/instagram/instagram-base.action.ts +393 -368
- package/src/providers/linkedin/actions/create-article.action.ts +266 -275
- package/src/providers/linkedin/actions/create-post.action.ts +177 -179
- package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
- package/src/providers/linkedin/actions/get-organization-posts.action.ts +147 -146
- package/src/providers/linkedin/actions/get-personal-posts.action.ts +139 -138
- package/src/providers/linkedin/actions/get-post-analytics.action.ts +189 -190
- package/src/providers/linkedin/actions/schedule-post.action.ts +189 -191
- package/src/providers/linkedin/actions/search-posts.action.ts +283 -275
- package/src/providers/linkedin/linkedin-base.action.ts +421 -407
- package/src/providers/tiktok/tiktok-base.action.ts +320 -305
- package/src/providers/twitter/actions/create-thread.action.ts +207 -203
- package/src/providers/twitter/actions/create-tweet.action.ts +188 -187
- package/src/providers/twitter/actions/delete-tweet.action.ts +129 -128
- package/src/providers/twitter/actions/get-analytics.action.ts +411 -402
- package/src/providers/twitter/actions/get-mentions.action.ts +219 -218
- package/src/providers/twitter/actions/get-timeline.action.ts +233 -232
- package/src/providers/twitter/actions/schedule-tweet.action.ts +222 -221
- package/src/providers/twitter/actions/search-tweets.action.ts +543 -540
- package/src/providers/twitter/twitter-base.action.ts +560 -541
- package/src/providers/youtube/youtube-base.action.ts +333 -320
|
@@ -2,7 +2,7 @@ import { RegisterClass } from '@memberjunction/global';
|
|
|
2
2
|
import { FacebookBaseAction, FacebookInsight } 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/core';
|
|
6
6
|
import axios from 'axios';
|
|
7
7
|
import { BaseAction } from '@memberjunction/actions';
|
|
8
8
|
|
|
@@ -12,312 +12,328 @@ import { BaseAction } from '@memberjunction/actions';
|
|
|
12
12
|
*/
|
|
13
13
|
@RegisterClass(BaseAction, 'FacebookGetPostInsightsAction')
|
|
14
14
|
export class FacebookGetPostInsightsAction extends FacebookBaseAction {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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: 'MetricTypes',
|
|
35
|
-
Type: 'Input',
|
|
36
|
-
Value: null,
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
Name: 'Period',
|
|
40
|
-
Type: 'Input',
|
|
41
|
-
Value: 'lifetime',
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
Name: 'IncludeVideoMetrics',
|
|
45
|
-
Type: 'Input',
|
|
46
|
-
Value: true,
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
Name: 'IncludeDemographics',
|
|
50
|
-
Type: 'Input',
|
|
51
|
-
Value: true,
|
|
52
|
-
},
|
|
53
|
-
];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Execute the action
|
|
58
|
-
*/
|
|
59
|
-
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
|
|
60
|
-
const { Params, ContextUser } = params;
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
// Validate required parameters
|
|
64
|
-
const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
|
|
65
|
-
const postId = this.getParamValue(Params, 'PostID');
|
|
66
|
-
|
|
67
|
-
if (!companyIntegrationId) {
|
|
68
|
-
return {
|
|
69
|
-
Success: false,
|
|
70
|
-
Message: 'CompanyIntegrationID is required',
|
|
71
|
-
ResultCode: 'INVALID_TOKEN',
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (!postId) {
|
|
76
|
-
return {
|
|
77
|
-
Success: false,
|
|
78
|
-
Message: 'PostID is required',
|
|
79
|
-
ResultCode: 'MISSING_REQUIRED_PARAM',
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Initialize OAuth
|
|
84
|
-
if (!(await this.initializeOAuth(companyIntegrationId))) {
|
|
85
|
-
return {
|
|
86
|
-
Success: false,
|
|
87
|
-
Message: 'Failed to initialize Facebook OAuth connection',
|
|
88
|
-
ResultCode: 'INVALID_TOKEN',
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Get parameters
|
|
93
|
-
const metricTypes = this.getParamValue(Params, 'MetricTypes') as string[];
|
|
94
|
-
const period = (this.getParamValue(Params, 'Period') as string) || 'lifetime';
|
|
95
|
-
const includeVideoMetrics = this.getParamValue(Params, 'IncludeVideoMetrics') !== false;
|
|
96
|
-
const includeDemographics = this.getParamValue(Params, 'IncludeDemographics') !== false;
|
|
97
|
-
|
|
98
|
-
LogStatus(`Retrieving insights for Facebook post ${postId}...`);
|
|
99
|
-
|
|
100
|
-
// Extract page ID from post ID (format: pageId_postId)
|
|
101
|
-
const pageId = postId.split('_')[0];
|
|
102
|
-
|
|
103
|
-
// Get page access token
|
|
104
|
-
const pageToken = await this.getPageAccessToken(pageId);
|
|
105
|
-
|
|
106
|
-
// Build metrics list
|
|
107
|
-
const metrics = metricTypes && metricTypes.length > 0 ? metricTypes : this.getDefaultPostMetrics(includeVideoMetrics);
|
|
108
|
-
|
|
109
|
-
// Get post insights
|
|
110
|
-
const insightsResponse = await axios.get(`${this.apiBaseUrl}/${postId}/insights`, {
|
|
111
|
-
params: {
|
|
112
|
-
access_token: pageToken,
|
|
113
|
-
metric: metrics.join(','),
|
|
114
|
-
period: period,
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
const insights: FacebookInsight[] = insightsResponse.data.data || [];
|
|
119
|
-
|
|
120
|
-
// Get additional engagement data
|
|
121
|
-
const engagementResponse = await axios.get(`${this.apiBaseUrl}/${postId}`, {
|
|
122
|
-
params: {
|
|
123
|
-
access_token: pageToken,
|
|
124
|
-
fields: 'reactions.summary(true).limit(0),comments.summary(true).limit(0),shares,likes.summary(true).limit(0)',
|
|
125
|
-
},
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
const engagementData = engagementResponse.data;
|
|
129
|
-
|
|
130
|
-
// Get demographic insights if requested
|
|
131
|
-
let demographics = null;
|
|
132
|
-
if (includeDemographics) {
|
|
133
|
-
demographics = await this.getPostDemographics(postId, pageToken);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Get post details for context
|
|
137
|
-
const postDetails = await this.getPost(postId);
|
|
138
|
-
|
|
139
|
-
// Process and organize insights
|
|
140
|
-
const processedInsights = this.processInsights(insights);
|
|
141
|
-
|
|
142
|
-
// Build comprehensive analytics object
|
|
143
|
-
const analytics = {
|
|
144
|
-
postId,
|
|
145
|
-
postDetails: {
|
|
146
|
-
message: postDetails.message,
|
|
147
|
-
createdTime: postDetails.created_time,
|
|
148
|
-
type: postDetails.attachments?.data?.[0]?.type || 'status',
|
|
149
|
-
permalinkUrl: postDetails.permalink_url,
|
|
150
|
-
},
|
|
151
|
-
metrics: processedInsights,
|
|
152
|
-
engagement: {
|
|
153
|
-
reactions: {
|
|
154
|
-
total: engagementData.reactions?.summary?.total_count || 0,
|
|
155
|
-
likes: engagementData.likes?.summary?.total_count || 0,
|
|
156
|
-
},
|
|
157
|
-
comments: engagementData.comments?.summary?.total_count || 0,
|
|
158
|
-
shares: engagementData.shares?.count || 0,
|
|
159
|
-
},
|
|
160
|
-
demographics,
|
|
161
|
-
period,
|
|
162
|
-
retrievedAt: new Date().toISOString(),
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
// Calculate engagement rate if we have reach data
|
|
166
|
-
const reach = processedInsights.post_impressions_unique || processedInsights.post_reach;
|
|
167
|
-
if (reach && reach > 0) {
|
|
168
|
-
const totalEngagements = analytics.engagement.reactions.total + analytics.engagement.comments + analytics.engagement.shares;
|
|
169
|
-
(analytics as any).engagementRate = (totalEngagements / reach) * 100;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
LogStatus(`Successfully retrieved insights for post ${postId}`);
|
|
173
|
-
|
|
174
|
-
// Update output parameters
|
|
175
|
-
const outputParams = [...Params];
|
|
176
|
-
// TODO: Set output parameters based on result
|
|
177
|
-
|
|
178
|
-
return {
|
|
179
|
-
Success: true,
|
|
180
|
-
Message: 'Post insights retrieved successfully',
|
|
181
|
-
ResultCode: 'SUCCESS',
|
|
182
|
-
Params: outputParams,
|
|
183
|
-
};
|
|
184
|
-
} catch (error) {
|
|
185
|
-
LogError(`Failed to get Facebook post insights: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
186
|
-
|
|
187
|
-
if (this.isAuthError(error)) {
|
|
188
|
-
return this.handleOAuthError(error);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Check if it's a permissions error
|
|
192
|
-
if (error instanceof Error && error.message.includes('permissions')) {
|
|
193
|
-
return {
|
|
194
|
-
Success: false,
|
|
195
|
-
Message: 'Insufficient permissions to access post insights. Ensure the page token has insights permissions.',
|
|
196
|
-
ResultCode: 'INSUFFICIENT_PERMISSIONS',
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return {
|
|
201
|
-
Success: false,
|
|
202
|
-
Message: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
203
|
-
ResultCode: 'ERROR',
|
|
204
|
-
};
|
|
15
|
+
/**
|
|
16
|
+
* Get action description
|
|
17
|
+
*/
|
|
18
|
+
public get Description(): string {
|
|
19
|
+
return 'Retrieves detailed analytics and insights for a specific Facebook post including reach, impressions, and engagement metrics';
|
|
205
20
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
];
|
|
240
|
-
|
|
241
|
-
if (includeVideo) {
|
|
242
|
-
metrics.push(
|
|
243
|
-
'post_video_views',
|
|
244
|
-
'post_video_views_unique',
|
|
245
|
-
'post_video_views_10s',
|
|
246
|
-
'post_video_views_10s_unique',
|
|
247
|
-
'post_video_avg_time_watched',
|
|
248
|
-
'post_video_complete_views_30s',
|
|
249
|
-
'post_video_complete_views_30s_unique',
|
|
250
|
-
'post_video_retention_graph',
|
|
251
|
-
'post_video_view_time',
|
|
252
|
-
'post_video_view_time_by_age_bucket_and_gender',
|
|
253
|
-
'post_video_view_time_by_region_id'
|
|
254
|
-
);
|
|
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: 'MetricTypes',
|
|
35
|
+
Type: 'Input',
|
|
36
|
+
Value: null,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
Name: 'Period',
|
|
40
|
+
Type: 'Input',
|
|
41
|
+
Value: 'lifetime',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
Name: 'IncludeVideoMetrics',
|
|
45
|
+
Type: 'Input',
|
|
46
|
+
Value: true,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
Name: 'IncludeDemographics',
|
|
50
|
+
Type: 'Input',
|
|
51
|
+
Value: true,
|
|
52
|
+
}
|
|
53
|
+
];
|
|
255
54
|
}
|
|
256
55
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Execute the action
|
|
58
|
+
*/
|
|
59
|
+
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
|
|
60
|
+
const { Params, ContextUser } = params;
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
// Validate required parameters
|
|
64
|
+
const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
|
|
65
|
+
const postId = this.getParamValue(Params, 'PostID');
|
|
66
|
+
|
|
67
|
+
if (!companyIntegrationId) {
|
|
68
|
+
return {
|
|
69
|
+
Success: false,
|
|
70
|
+
Message: 'CompanyIntegrationID is required',
|
|
71
|
+
ResultCode: 'INVALID_TOKEN'
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!postId) {
|
|
76
|
+
return {
|
|
77
|
+
Success: false,
|
|
78
|
+
Message: 'PostID is required',
|
|
79
|
+
ResultCode: 'MISSING_REQUIRED_PARAM'
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Initialize OAuth
|
|
84
|
+
if (!await this.initializeOAuth(companyIntegrationId)) {
|
|
85
|
+
return {
|
|
86
|
+
Success: false,
|
|
87
|
+
Message: 'Failed to initialize Facebook OAuth connection',
|
|
88
|
+
ResultCode: 'INVALID_TOKEN'
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Get parameters
|
|
93
|
+
const metricTypes = this.getParamValue(Params, 'MetricTypes') as string[];
|
|
94
|
+
const period = this.getParamValue(Params, 'Period') as string || 'lifetime';
|
|
95
|
+
const includeVideoMetrics = this.getParamValue(Params, 'IncludeVideoMetrics') !== false;
|
|
96
|
+
const includeDemographics = this.getParamValue(Params, 'IncludeDemographics') !== false;
|
|
97
|
+
|
|
98
|
+
LogStatus(`Retrieving insights for Facebook post ${postId}...`);
|
|
99
|
+
|
|
100
|
+
// Extract page ID from post ID (format: pageId_postId)
|
|
101
|
+
const pageId = postId.split('_')[0];
|
|
102
|
+
|
|
103
|
+
// Get page access token
|
|
104
|
+
const pageToken = await this.getPageAccessToken(pageId);
|
|
105
|
+
|
|
106
|
+
// Build metrics list
|
|
107
|
+
const metrics = metricTypes && metricTypes.length > 0
|
|
108
|
+
? metricTypes
|
|
109
|
+
: this.getDefaultPostMetrics(includeVideoMetrics);
|
|
110
|
+
|
|
111
|
+
// Get post insights
|
|
112
|
+
const insightsResponse = await axios.get(
|
|
113
|
+
`${this.apiBaseUrl}/${postId}/insights`,
|
|
114
|
+
{
|
|
115
|
+
params: {
|
|
116
|
+
access_token: pageToken,
|
|
117
|
+
metric: metrics.join(','),
|
|
118
|
+
period: period
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const insights: FacebookInsight[] = insightsResponse.data.data || [];
|
|
124
|
+
|
|
125
|
+
// Get additional engagement data
|
|
126
|
+
const engagementResponse = await axios.get(
|
|
127
|
+
`${this.apiBaseUrl}/${postId}`,
|
|
128
|
+
{
|
|
129
|
+
params: {
|
|
130
|
+
access_token: pageToken,
|
|
131
|
+
fields: 'reactions.summary(true).limit(0),comments.summary(true).limit(0),shares,likes.summary(true).limit(0)'
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const engagementData = engagementResponse.data;
|
|
137
|
+
|
|
138
|
+
// Get demographic insights if requested
|
|
139
|
+
let demographics = null;
|
|
140
|
+
if (includeDemographics) {
|
|
141
|
+
demographics = await this.getPostDemographics(postId, pageToken);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Get post details for context
|
|
145
|
+
const postDetails = await this.getPost(postId);
|
|
146
|
+
|
|
147
|
+
// Process and organize insights
|
|
148
|
+
const processedInsights = this.processInsights(insights);
|
|
149
|
+
|
|
150
|
+
// Build comprehensive analytics object
|
|
151
|
+
const analytics = {
|
|
152
|
+
postId,
|
|
153
|
+
postDetails: {
|
|
154
|
+
message: postDetails.message,
|
|
155
|
+
createdTime: postDetails.created_time,
|
|
156
|
+
type: postDetails.attachments?.data?.[0]?.type || 'status',
|
|
157
|
+
permalinkUrl: postDetails.permalink_url
|
|
158
|
+
},
|
|
159
|
+
metrics: processedInsights,
|
|
160
|
+
engagement: {
|
|
161
|
+
reactions: {
|
|
162
|
+
total: engagementData.reactions?.summary?.total_count || 0,
|
|
163
|
+
likes: engagementData.likes?.summary?.total_count || 0
|
|
164
|
+
},
|
|
165
|
+
comments: engagementData.comments?.summary?.total_count || 0,
|
|
166
|
+
shares: engagementData.shares?.count || 0
|
|
167
|
+
},
|
|
168
|
+
demographics,
|
|
169
|
+
period,
|
|
170
|
+
retrievedAt: new Date().toISOString()
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Calculate engagement rate if we have reach data
|
|
174
|
+
const reach = processedInsights.post_impressions_unique || processedInsights.post_reach;
|
|
175
|
+
if (reach && reach > 0) {
|
|
176
|
+
const totalEngagements = analytics.engagement.reactions.total +
|
|
177
|
+
analytics.engagement.comments +
|
|
178
|
+
analytics.engagement.shares;
|
|
179
|
+
(analytics as any).engagementRate = (totalEngagements / reach) * 100;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
LogStatus(`Successfully retrieved insights for post ${postId}`);
|
|
183
|
+
|
|
184
|
+
// Update output parameters
|
|
185
|
+
const outputParams = [...Params];
|
|
186
|
+
// TODO: Set output parameters based on result
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
Success: true,
|
|
190
|
+
Message: 'Post insights retrieved successfully',
|
|
191
|
+
ResultCode: 'SUCCESS',
|
|
192
|
+
Params: outputParams
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
} catch (error) {
|
|
196
|
+
LogError(`Failed to get Facebook post insights: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
197
|
+
|
|
198
|
+
if (this.isAuthError(error)) {
|
|
199
|
+
return this.handleOAuthError(error);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Check if it's a permissions error
|
|
203
|
+
if (error instanceof Error && error.message.includes('permissions')) {
|
|
204
|
+
return {
|
|
205
|
+
Success: false,
|
|
206
|
+
Message: 'Insufficient permissions to access post insights. Ensure the page token has insights permissions.',
|
|
207
|
+
ResultCode: 'INSUFFICIENT_PERMISSIONS'
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
Success: false,
|
|
213
|
+
Message: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
214
|
+
ResultCode: 'ERROR'
|
|
215
|
+
};
|
|
284
216
|
}
|
|
285
|
-
|
|
217
|
+
}
|
|
286
218
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
219
|
+
/**
|
|
220
|
+
* Get default post metrics based on post type
|
|
221
|
+
*/
|
|
222
|
+
private getDefaultPostMetrics(includeVideo: boolean): string[] {
|
|
223
|
+
const metrics = [
|
|
224
|
+
// Reach and impressions
|
|
225
|
+
'post_impressions',
|
|
226
|
+
'post_impressions_unique',
|
|
227
|
+
'post_impressions_paid',
|
|
228
|
+
'post_impressions_paid_unique',
|
|
229
|
+
'post_impressions_fan',
|
|
230
|
+
'post_impressions_fan_unique',
|
|
231
|
+
'post_impressions_organic',
|
|
232
|
+
'post_impressions_organic_unique',
|
|
233
|
+
|
|
234
|
+
// Engagement
|
|
235
|
+
'post_engaged_users',
|
|
236
|
+
'post_engaged_fan',
|
|
237
|
+
'post_clicks',
|
|
238
|
+
'post_clicks_unique',
|
|
239
|
+
|
|
240
|
+
// Reactions
|
|
241
|
+
'post_reactions_by_type_total',
|
|
242
|
+
|
|
243
|
+
// Negative feedback
|
|
244
|
+
'post_negative_feedback',
|
|
245
|
+
'post_negative_feedback_unique',
|
|
246
|
+
|
|
247
|
+
// Activity
|
|
248
|
+
'post_activity',
|
|
249
|
+
'post_activity_by_action_type'
|
|
250
|
+
];
|
|
251
|
+
|
|
252
|
+
if (includeVideo) {
|
|
253
|
+
metrics.push(
|
|
254
|
+
'post_video_views',
|
|
255
|
+
'post_video_views_unique',
|
|
256
|
+
'post_video_views_10s',
|
|
257
|
+
'post_video_views_10s_unique',
|
|
258
|
+
'post_video_avg_time_watched',
|
|
259
|
+
'post_video_complete_views_30s',
|
|
260
|
+
'post_video_complete_views_30s_unique',
|
|
261
|
+
'post_video_retention_graph',
|
|
262
|
+
'post_video_view_time',
|
|
263
|
+
'post_video_view_time_by_age_bucket_and_gender',
|
|
264
|
+
'post_video_view_time_by_region_id'
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return metrics;
|
|
291
269
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get demographic insights for a post
|
|
273
|
+
*/
|
|
274
|
+
private async getPostDemographics(postId: string, pageToken: string): Promise<any> {
|
|
275
|
+
try {
|
|
276
|
+
const demographicMetrics = [
|
|
277
|
+
'post_impressions_by_age_gender_unique',
|
|
278
|
+
'post_engaged_users_by_age_gender',
|
|
279
|
+
'post_clicks_by_age_gender_unique'
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
const response = await axios.get(
|
|
283
|
+
`${this.apiBaseUrl}/${postId}/insights`,
|
|
284
|
+
{
|
|
285
|
+
params: {
|
|
286
|
+
access_token: pageToken,
|
|
287
|
+
metric: demographicMetrics.join(',')
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const insights = response.data.data || [];
|
|
293
|
+
const demographics: Record<string, any> = {};
|
|
294
|
+
|
|
295
|
+
for (const insight of insights) {
|
|
296
|
+
if (insight.values?.[0]?.value) {
|
|
297
|
+
demographics[insight.name] = insight.values[0].value;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return demographics;
|
|
302
|
+
} catch (error) {
|
|
303
|
+
LogError(`Failed to get demographic insights: ${error}`);
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Process raw insights into a more usable format
|
|
310
|
+
*/
|
|
311
|
+
private processInsights(insights: FacebookInsight[]): Record<string, any> {
|
|
312
|
+
const processed: Record<string, any> = {};
|
|
313
|
+
|
|
314
|
+
for (const insight of insights) {
|
|
315
|
+
const value = insight.values?.[0]?.value;
|
|
316
|
+
|
|
317
|
+
if (value !== undefined) {
|
|
318
|
+
// Handle different value types
|
|
319
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
320
|
+
// For metrics like reactions_by_type
|
|
321
|
+
processed[insight.name] = value;
|
|
322
|
+
} else {
|
|
323
|
+
processed[insight.name] = value;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Add metadata
|
|
327
|
+
processed[`${insight.name}_meta`] = {
|
|
328
|
+
title: insight.title,
|
|
329
|
+
description: insight.description,
|
|
330
|
+
period: insight.period
|
|
331
|
+
};
|
|
332
|
+
}
|
|
310
333
|
}
|
|
311
334
|
|
|
312
|
-
|
|
313
|
-
processed[`${insight.name}_meta`] = {
|
|
314
|
-
title: insight.title,
|
|
315
|
-
description: insight.description,
|
|
316
|
-
period: insight.period,
|
|
317
|
-
};
|
|
318
|
-
}
|
|
335
|
+
return processed;
|
|
319
336
|
}
|
|
320
337
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
338
|
+
|
|
339
|
+
}
|