Skip to content
Social SDK Cloud, the hosted SDK, is taking early-access signups.Join the list
Social SDK megaphone markSocial SDK
Esc
↑↓navigate↵open⌘Jpreview
On this page

Analytics reports

Read account metrics and native analytics reports for YouTube, X, Bluesky, Threads, Instagram, LinkedIn, and TikTok, with the scopes and limits each one needs.

Analytics has two normalized reads:

const metrics = await social.analytics.getAccountMetrics(account);
const report = await social.analytics.getReport(account, {
  from: "2026-01-01",
  to: "2026-01-31",
  metrics: ["views"],
});

getAccountMetrics and getPostMetrics return MetricValue[]. Items contain name, numeric value, unit, period, fetchedAt, freshness, and source. getReport returns { query, rows, fetchedAt, source }; each row contains dimensions and numeric metrics. The query also accepts dimensions, such as ["day"]. There is no cursor or iterate method. The client validates ordered YYYY-MM-DD dates, at least one metric, and nonempty names. Invalid input raises invalid_input.

Each metric keeps its existing provider name and adds canonicalName when the counter has a portable equivalent: views, likes, comments, shares, impressions, reach, saves, clicks, followers, or profile_views. For example, YouTube’s viewCount maps to views, X’s replies maps to comments, and bookmarks maps to saves. Direct adapters and managed backends use the same projection. Unknown metrics retain their name without a canonical name; rates and watch time are not relabeled as counters.

const metrics = await social.analytics.getPostMetrics(post);
const views = metrics.find((metric) => metric.canonicalName === "views")?.value;

Units and reporting periods remain provider-specific. Match the period and source before comparing or adding values, since multiple provider counters can share a canonical name. A missing counter means the provider did not return it, not zero. The tabs below list each route’s existing names and periods.

The examples assume one social client built with the platform’s adapter and an account from connectedAccountRef, using the platform’s own account ID.

Platform support

Only YouTube implements the normalized analytics.report.read. Every tab below supports getAccountMetrics. An unavailable operation raises unsupported_capability.

YouTube

Account metrics and reports. The two reads use different APIs and scopes:

  • getAccountMetrics reads channel statistics from the YouTube Data API and needs https://www.googleapis.com/auth/youtube.readonly.
  • getReport calls YouTube Analytics and needs https://www.googleapis.com/auth/yt-analytics.readonly. Revenue metrics also need https://www.googleapis.com/auth/yt-analytics-monetary.readonly.

Report dates must be bounded and metric names provider-safe. YouTube Analytics data can lag by a day or more.

Configure youtube({ auth: { accessToken, channelId } }). The adapter calls YouTube Analytics reports.query:

const report = await social.analytics.getReport(account, {
  from: "2026-01-01",
  to: "2026-01-31",
  metrics: ["views", "estimatedMinutesWatched"],
  dimensions: ["day"],
});

A row can look like { dimensions: { day: "2026-01-03" }, metrics: { views: 1842, estimatedMinutesWatched: 96.5 } }. YouTube can omit rows for an empty period; the SDK returns rows: []. Account metrics are lifetime channel viewCount, subscriberCount (omitted when the channel hides it), and videoCount. Post metrics are lifetime viewCount, likeCount, and commentCount.

X

Account metrics only. Needs a user OAuth token and current X API access and billing.

Configure x({ auth: { userId, accessToken } }). appBearerToken is for other X operations, not this read.

const metrics = await social.analytics.getAccountMetrics(account);
const followers = metrics.find((metric) => metric.name === "followers_count")?.value;

Account items are lifetime profile public metrics: followers_count, following_count, tweet_count, and listed_count when returned. X has no normalized bounded report. Post metrics are lifetime likes, reposts, replies, quotes, impressions, and bookmarks, renamed from X’s *_count fields, each only when X returns it.

Bluesky

Account metrics only, from a profile snapshot. Needs the account DID and a JWT or OAuth session.

Configure bluesky({ auth: { service, did, accessJwt } }), or pass session instead of accessJwt. The snapshot contains lifetime followers, following, and posts. Post metrics are likes, reposts, replies, and quotes. Bluesky has no date-range report.

const metrics = await social.analytics.getAccountMetrics(account);

Threads

Account and post metrics. Needs the OAuth scopes threads_basic and threads_manage_insights.

Configure threads({ auth: { userId, accessToken } }), with an optional graphVersion. getAccountMetrics requests views, likes, replies, reposts, quotes, clicks, and followers_count. followers_count is a lifetime total. views comes back as daily values, and the SDK returns the latest day with that day as its period. The other totals have period: "unknown" because Meta does not state their window. Threads reports link clicks as link_total_values; the SDK renames it clicks.

getPostMetrics(post) requests views, likes, replies, reposts, quotes, shares, and clicks (again renamed from link_total_values), with period: "lifetime". Any metric Meta omits is left out. Threads has no normalized account report.

const metrics = await social.analytics.getAccountMetrics(account);
const post = await social.analytics.getPostMetrics(platformPostRef({ ...account, postId }));

Instagram

Account metrics only. Instagram Login needs instagram_business_basic and instagram_business_manage_insights. Facebook Login needs instagram_basic, instagram_manage_insights, and pages_read_engagement.

Configure instagram({ auth: { accessToken, accountId, flavor } }) with the flavor that matches your granted permissions. The lifetime account items are followers_count and media_count. Post metrics depend on the media type: feed posts and reels request likes, comments, saved, shares, and reach; stories request only shares and reach. Meta may return fewer. Instagram has no normalized bounded report.

const metrics = await social.analytics.getAccountMetrics(account);
const post = await social.analytics.getPostMetrics(
  platformPostRef({ ...account, postId: mediaId }),
);

LinkedIn

Account metrics for organizations, plus native organization statistics. Needs Community Management API access and rw_organization_admin or r_organization_admin. Member accounts are not eligible.

Configure linkedin() with an organization author URN such as urn:li:organization:123. getAccountMetrics returns the organization’s lifetime follower count. Follower, page, and share statistics are native:

import { connectedAccountRef } from "@opencoredev/social-sdk";
import type { LinkedInTimeInterval } from "@opencoredev/social-sdk/linkedin";

const author = process.env.LINKEDIN_ORGANIZATION_URN;
if (author === undefined || !/^urn:li:organization:\d+$/.test(author)) {
  throw new Error("Set LINKEDIN_ORGANIZATION_URN to urn:li:organization:<id>");
}
const account = connectedAccountRef({
  backend: "default",
  platform: "linkedin",
  accountId: author,
});

const native = social.native("default", { acknowledgeUnsafe: true });
if (native === undefined) throw new Error("This adapter has no native module");

const interval: LinkedInTimeInterval = {
  granularity: "DAY",
  start: Date.parse("2026-01-01"),
  end: Date.parse("2026-01-31"),
};
const rows = await native.getOrganizationFollowerStatistics({ account, interval, context });

Type the interval as LinkedInTimeInterval, or write it inline in the call. A separately declared object literal widens granularity to string, which does not type-check.

Use getOrganizationPageStatistics and getOrganizationShareStatistics for the other reports. Follower intervals accept DAY, WEEK, or MONTH. Page and share intervals accept only DAY or MONTH. Use LinkedInPageShareTimeInterval for reusable page/share intervals and LinkedInTimeInterval for followers. A time-bound interval requires start. A follower row contains the organization, interval, gains, and breakdowns. Native calls bypass client authorization middleware.

TikTok

Account metrics, and post metrics through analytics.read. Account metrics need user.info.stats; post metrics need video.list.

Configure tiktok() with the creator openId, an access token, and verified media origins. The lifetime account items are follower_count, following_count, likes_count, and video_count. getPostMetrics(post) returns like_count, comment_count, share_count, and view_count for one video. TikTok has no normalized report method.

const metrics = await social.analytics.getAccountMetrics(account);
const video = await social.analytics.getPostMetrics(
  platformPostRef({ ...account, postId: videoId }),
);

Errors

Credential or account identity mismatches raise unauthorized. A missing capability raises unsupported_capability. Provider throttling and transport failures keep their SocialError codes. An empty successful result is valid and does not prove that historical values are zero.

Last updated on October 26, 2026