@memberjunction/actions-bizapps-social 2.111.0 → 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, 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/global';
|
|
6
6
|
import axios from 'axios';
|
|
7
7
|
import { BaseAction } from '@memberjunction/actions';
|
|
8
8
|
|
|
@@ -12,328 +12,312 @@ import { BaseAction } from '@memberjunction/actions';
|
|
|
12
12
|
*/
|
|
13
13
|
@RegisterClass(BaseAction, 'FacebookGetPostInsightsAction')
|
|
14
14
|
export class FacebookGetPostInsightsAction extends FacebookBaseAction {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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';
|
|
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
|
+
};
|
|
20
205
|
}
|
|
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
|
-
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Get default post metrics based on post type
|
|
210
|
+
*/
|
|
211
|
+
private getDefaultPostMetrics(includeVideo: boolean): string[] {
|
|
212
|
+
const metrics = [
|
|
213
|
+
// Reach and impressions
|
|
214
|
+
'post_impressions',
|
|
215
|
+
'post_impressions_unique',
|
|
216
|
+
'post_impressions_paid',
|
|
217
|
+
'post_impressions_paid_unique',
|
|
218
|
+
'post_impressions_fan',
|
|
219
|
+
'post_impressions_fan_unique',
|
|
220
|
+
'post_impressions_organic',
|
|
221
|
+
'post_impressions_organic_unique',
|
|
222
|
+
|
|
223
|
+
// Engagement
|
|
224
|
+
'post_engaged_users',
|
|
225
|
+
'post_engaged_fan',
|
|
226
|
+
'post_clicks',
|
|
227
|
+
'post_clicks_unique',
|
|
228
|
+
|
|
229
|
+
// Reactions
|
|
230
|
+
'post_reactions_by_type_total',
|
|
231
|
+
|
|
232
|
+
// Negative feedback
|
|
233
|
+
'post_negative_feedback',
|
|
234
|
+
'post_negative_feedback_unique',
|
|
235
|
+
|
|
236
|
+
// Activity
|
|
237
|
+
'post_activity',
|
|
238
|
+
'post_activity_by_action_type',
|
|
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
|
+
);
|
|
54
255
|
}
|
|
55
256
|
|
|
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
|
-
// 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
|
-
};
|
|
257
|
+
return metrics;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Get demographic insights for a post
|
|
262
|
+
*/
|
|
263
|
+
private async getPostDemographics(postId: string, pageToken: string): Promise<any> {
|
|
264
|
+
try {
|
|
265
|
+
const demographicMetrics = [
|
|
266
|
+
'post_impressions_by_age_gender_unique',
|
|
267
|
+
'post_engaged_users_by_age_gender',
|
|
268
|
+
'post_clicks_by_age_gender_unique',
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
const response = await axios.get(`${this.apiBaseUrl}/${postId}/insights`, {
|
|
272
|
+
params: {
|
|
273
|
+
access_token: pageToken,
|
|
274
|
+
metric: demographicMetrics.join(','),
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
const insights = response.data.data || [];
|
|
279
|
+
const demographics: Record<string, any> = {};
|
|
280
|
+
|
|
281
|
+
for (const insight of insights) {
|
|
282
|
+
if (insight.values?.[0]?.value) {
|
|
283
|
+
demographics[insight.name] = insight.values[0].value;
|
|
216
284
|
}
|
|
217
|
-
|
|
285
|
+
}
|
|
218
286
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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;
|
|
287
|
+
return demographics;
|
|
288
|
+
} catch (error) {
|
|
289
|
+
LogError(`Failed to get demographic insights: ${error}`);
|
|
290
|
+
return null;
|
|
269
291
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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
|
-
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Process raw insights into a more usable format
|
|
296
|
+
*/
|
|
297
|
+
private processInsights(insights: FacebookInsight[]): Record<string, any> {
|
|
298
|
+
const processed: Record<string, any> = {};
|
|
299
|
+
|
|
300
|
+
for (const insight of insights) {
|
|
301
|
+
const value = insight.values?.[0]?.value;
|
|
302
|
+
|
|
303
|
+
if (value !== undefined) {
|
|
304
|
+
// Handle different value types
|
|
305
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
306
|
+
// For metrics like reactions_by_type
|
|
307
|
+
processed[insight.name] = value;
|
|
308
|
+
} else {
|
|
309
|
+
processed[insight.name] = value;
|
|
333
310
|
}
|
|
334
311
|
|
|
335
|
-
|
|
312
|
+
// Add metadata
|
|
313
|
+
processed[`${insight.name}_meta`] = {
|
|
314
|
+
title: insight.title,
|
|
315
|
+
description: insight.description,
|
|
316
|
+
period: insight.period,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
336
319
|
}
|
|
337
320
|
|
|
338
|
-
|
|
339
|
-
}
|
|
321
|
+
return processed;
|
|
322
|
+
}
|
|
323
|
+
}
|