@memberjunction/actions-bizapps-social
Version:
Social Media Actions for MemberJunction - Twitter, LinkedIn, Facebook, Instagram, TikTok, YouTube, HootSuite, Buffer
360 lines • 15.2 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FacebookGetPageInsightsAction = void 0;
const global_1 = require("@memberjunction/global");
const facebook_base_action_1 = require("../facebook-base.action");
const core_1 = require("@memberjunction/core");
const axios_1 = __importDefault(require("axios"));
const actions_1 = require("@memberjunction/actions");
/**
* Retrieves comprehensive analytics and insights for a Facebook page.
* Provides metrics like page views, likes, engagement, demographics, and more.
*/
let FacebookGetPageInsightsAction = class FacebookGetPageInsightsAction extends facebook_base_action_1.FacebookBaseAction {
/**
* Get action description
*/
get Description() {
return 'Retrieves comprehensive analytics for a Facebook page including views, engagement, demographics, and performance metrics';
}
/**
* Define the parameters for this action
*/
get Params() {
return [
...this.commonSocialParams,
{
Name: 'PageID',
Type: 'Input',
Value: null,
},
{
Name: 'MetricTypes',
Type: 'Input',
Value: null,
},
{
Name: 'Period',
Type: 'Input',
Value: 'day',
},
{
Name: 'StartDate',
Type: 'Input',
Value: null,
},
{
Name: 'EndDate',
Type: 'Input',
Value: null,
},
{
Name: 'IncludeDemographics',
Type: 'Input',
Value: true,
},
{
Name: 'IncludeVideoMetrics',
Type: 'Input',
Value: true,
},
{
Name: 'CompareWithPrevious',
Type: 'Input',
Value: false,
}
];
}
/**
* Execute the action
*/
async InternalRunAction(params) {
const { Params, ContextUser } = params;
try {
// Validate required parameters
const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
const pageId = this.getParamValue(Params, 'PageID');
if (!companyIntegrationId) {
return {
Success: false,
Message: 'CompanyIntegrationID is required',
ResultCode: 'INVALID_TOKEN'
};
}
if (!pageId) {
return {
Success: false,
Message: 'PageID is required',
ResultCode: 'MISSING_REQUIRED_PARAM'
};
}
// Initialize OAuth
if (!await this.initializeOAuth(companyIntegrationId)) {
return {
Success: false,
Message: 'Failed to initialize Facebook OAuth connection',
ResultCode: 'INVALID_TOKEN'
};
}
// Get parameters
const metricTypes = this.getParamValue(Params, 'MetricTypes');
const period = this.getParamValue(Params, 'Period') || 'day';
const startDate = this.getParamValue(Params, 'StartDate');
const endDate = this.getParamValue(Params, 'EndDate');
const includeDemographics = this.getParamValue(Params, 'IncludeDemographics') !== false;
const includeVideoMetrics = this.getParamValue(Params, 'IncludeVideoMetrics') !== false;
const compareWithPrevious = this.getParamValue(Params, 'CompareWithPrevious');
(0, core_1.LogStatus)(`Retrieving insights for Facebook page ${pageId}...`);
// Get page access token
const pageToken = await this.getPageAccessToken(pageId);
// Build metrics list
const metrics = metricTypes && metricTypes.length > 0
? metricTypes
: this.getDefaultPageMetrics(includeDemographics, includeVideoMetrics);
// Build date range parameters
const dateParams = {};
if (startDate && endDate) {
dateParams.since = new Date(startDate).toISOString();
dateParams.until = new Date(endDate).toISOString();
}
else if (period !== 'lifetime') {
// Default to last 30 days if no date range specified
const end = new Date();
const start = new Date();
start.setDate(start.getDate() - 30);
dateParams.since = start.toISOString();
dateParams.until = end.toISOString();
}
// Get page insights
const insightsResponse = await axios_1.default.get(`${this.apiBaseUrl}/${pageId}/insights`, {
params: {
access_token: pageToken,
metric: metrics.join(','),
period: period,
...dateParams
}
});
const insights = insightsResponse.data.data || [];
// Get page info for context
const pageInfoResponse = await axios_1.default.get(`${this.apiBaseUrl}/${pageId}`, {
params: {
access_token: pageToken,
fields: 'id,name,category,fan_count,followers_count,about,cover,picture'
}
});
const pageInfo = pageInfoResponse.data;
// Process insights into categories
const processedInsights = this.categorizeInsights(insights);
// Get comparison data if requested
let comparison = null;
if (compareWithPrevious && startDate && endDate) {
comparison = await this.getComparisonData(pageId, pageToken, metrics, period, new Date(startDate), new Date(endDate));
}
// Calculate summary metrics
const summary = this.calculateSummaryMetrics(processedInsights, pageInfo);
(0, core_1.LogStatus)(`Successfully retrieved insights for page ${pageId}`);
return {
Success: true,
Message: 'Page insights retrieved successfully',
ResultCode: 'SUCCESS',
Params
};
}
catch (error) {
(0, core_1.LogError)(`Failed to get Facebook page insights: ${error instanceof Error ? error.message : 'Unknown error'}`);
if (this.isAuthError(error)) {
return this.handleOAuthError(error);
}
return {
Success: false,
Message: error instanceof Error ? error.message : 'Unknown error occurred',
ResultCode: 'ERROR'
};
}
}
/**
* Get default page metrics based on options
*/
getDefaultPageMetrics(includeDemographics, includeVideo) {
const metrics = [
// Page Views
'page_views_total',
'page_views_logged_in_unique',
'page_views_by_site_logged_in_unique',
// Page Likes
'page_fan_adds',
'page_fan_removes',
'page_fan_adds_unique',
'page_fans',
// Engagement
'page_engaged_users',
'page_post_engagements',
'page_consumptions',
'page_consumptions_unique',
'page_places_checkin_total',
// Impressions
'page_impressions',
'page_impressions_unique',
'page_impressions_paid',
'page_impressions_paid_unique',
'page_impressions_organic',
'page_impressions_organic_unique',
// Posts
'page_posts_impressions',
'page_posts_impressions_unique',
// Actions
'page_actions_post_reactions_total',
'page_actions_post_reactions_like_total',
'page_actions_post_reactions_love_total',
'page_actions_post_reactions_wow_total',
'page_actions_post_reactions_haha_total',
'page_actions_post_reactions_sorry_total',
'page_actions_post_reactions_anger_total',
// CTA Clicks
'page_total_actions',
'page_cta_clicks_logged_in_total',
// Messages
'page_messages_total_messaging_connections',
'page_messages_new_conversations',
// Negative Feedback
'page_negative_feedback',
'page_negative_feedback_unique'
];
if (includeDemographics) {
metrics.push('page_fans_gender_age', 'page_fans_country', 'page_fans_city', 'page_fans_locale', 'page_impressions_by_age_gender_unique', 'page_engaged_users_by_age_gender');
}
if (includeVideo) {
metrics.push('page_video_views', 'page_video_views_paid', 'page_video_views_organic', 'page_video_views_autoplayed', 'page_video_views_click_to_play', 'page_video_views_unique', 'page_video_repeat_views', 'page_video_complete_views_30s', 'page_video_complete_views_30s_paid', 'page_video_complete_views_30s_organic', 'page_video_views_10s', 'page_video_views_10s_paid', 'page_video_views_10s_organic');
}
return metrics;
}
/**
* Categorize insights by type for better organization
*/
categorizeInsights(insights) {
const categories = {
pageViews: {},
engagement: {},
likes: {},
impressions: {},
posts: {},
reactions: {},
demographics: {},
video: {},
messages: {},
negativeFeedback: {}
};
for (const insight of insights) {
const name = insight.name;
const value = insight.values?.[0]?.value;
if (name.includes('page_views')) {
categories.pageViews[name] = value;
}
else if (name.includes('engaged') || name.includes('engagement')) {
categories.engagement[name] = value;
}
else if (name.includes('fan') || name === 'page_fans') {
categories.likes[name] = value;
}
else if (name.includes('impressions')) {
categories.impressions[name] = value;
}
else if (name.includes('posts')) {
categories.posts[name] = value;
}
else if (name.includes('reactions')) {
categories.reactions[name] = value;
}
else if (name.includes('gender') || name.includes('country') || name.includes('city') || name.includes('locale')) {
categories.demographics[name] = value;
}
else if (name.includes('video')) {
categories.video[name] = value;
}
else if (name.includes('messages')) {
categories.messages[name] = value;
}
else if (name.includes('negative')) {
categories.negativeFeedback[name] = value;
}
}
return categories;
}
/**
* Calculate summary metrics
*/
calculateSummaryMetrics(insights, pageInfo) {
const summary = {
totalFans: pageInfo.fan_count || 0,
totalFollowers: pageInfo.followers_count || 0,
totalPageViews: insights.pageViews.page_views_total || 0,
totalEngagements: insights.engagement.page_engaged_users || 0,
totalImpressions: insights.impressions.page_impressions || 0,
netNewFans: (insights.likes.page_fan_adds || 0) - (insights.likes.page_fan_removes || 0)
};
// Calculate engagement rate if we have the data
if (summary.totalImpressions > 0) {
summary.engagementRate = (summary.totalEngagements / summary.totalImpressions) * 100;
}
// Add reaction breakdown
const reactions = insights.reactions;
if (reactions) {
summary.reactionBreakdown = {
total: reactions.page_actions_post_reactions_total || 0,
like: reactions.page_actions_post_reactions_like_total || 0,
love: reactions.page_actions_post_reactions_love_total || 0,
wow: reactions.page_actions_post_reactions_wow_total || 0,
haha: reactions.page_actions_post_reactions_haha_total || 0,
sorry: reactions.page_actions_post_reactions_sorry_total || 0,
anger: reactions.page_actions_post_reactions_anger_total || 0
};
}
return summary;
}
/**
* Get comparison data for previous period
*/
async getComparisonData(pageId, pageToken, metrics, period, startDate, endDate) {
try {
const duration = endDate.getTime() - startDate.getTime();
const previousStart = new Date(startDate.getTime() - duration);
const previousEnd = new Date(startDate.getTime());
const response = await axios_1.default.get(`${this.apiBaseUrl}/${pageId}/insights`, {
params: {
access_token: pageToken,
metric: metrics.join(','),
period: period,
since: previousStart.toISOString(),
until: previousEnd.toISOString()
}
});
const previousInsights = response.data.data || [];
const processedPrevious = this.categorizeInsights(previousInsights);
return {
period: {
start: previousStart.toISOString(),
end: previousEnd.toISOString()
},
insights: processedPrevious
};
}
catch (error) {
(0, core_1.LogError)(`Failed to get comparison data: ${error}`);
return null;
}
}
};
exports.FacebookGetPageInsightsAction = FacebookGetPageInsightsAction;
exports.FacebookGetPageInsightsAction = FacebookGetPageInsightsAction = __decorate([
(0, global_1.RegisterClass)(actions_1.BaseAction, 'FacebookGetPageInsightsAction')
], FacebookGetPageInsightsAction);
//# sourceMappingURL=get-page-insights.action.js.map