li_get_video_analytics
Retrieve video-specific performance metrics for LinkedIn campaigns, including video starts, views, and quartile completions. Compute video completion rates to evaluate ad quality. Scope to specific campaigns or report at account level.
Instructions
Fetch video-specific performance metrics for LinkedIn campaigns, broken down by creative. Returns videoStarts, videoViews, videoFirstQuartileCompletions, videoMidpointCompletions, videoThirdQuartileCompletions, videoCompletions, plus a computed videoCompletionRate (completions / starts × 100). Use to evaluate video ad quality — high completion rates indicate compelling content; low rates signal drop-off. Scope to specific campaigns via campaign_ids or report at account level.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| campaign_ids | No | Campaign numeric IDs or URNs to scope the report. Omit to report at account level. | |
| ad_account_id | No | ||
| start_date | No | 28daysAgo | |
| end_date | No | yesterday | |
| time_granularity | No | ALL |
Implementation Reference
- src/tools/analytics.ts:321-360 (handler)The getVideoAnalytics async function that executes the tool logic: resolves dates, builds analytics URL with CREATIVE pivot and VIDEO_FIELDS, fetches raw data via liGetRaw, enriches each element with a computed videoCompletionRate, and returns the enriched response.
export async function getVideoAnalytics(args: { campaign_ids?: string[]; ad_account_id?: string; start_date?: string; end_date?: string; time_granularity?: (typeof TIME_GRANULARITIES)[number]; }): Promise<AnalyticsResponse & { enriched?: unknown[] }> { const start = resolveDate(args.start_date ?? DEFAULT_START); const end = resolveDate(args.end_date ?? DEFAULT_END); const campaignUrns = args.campaign_ids?.map((id) => urn("sponsoredCampaign", id)); const accountUrn = campaignUrns && campaignUrns.length > 0 ? undefined : resolveAdAccount(args.ad_account_id); const url = buildAnalyticsUrl({ pivot: "CREATIVE", timeGranularity: args.time_granularity ?? "ALL", start, end, fields: VIDEO_FIELDS, campaignUrns, accountUrn, }); const raw = await liGetRaw<AnalyticsResponse>(url); // Compute completion rate per creative const enriched = (raw.elements ?? []).map((row) => { const starts = Number(row["videoStarts"] ?? row["videoViews"] ?? 0); const completions = Number(row["videoCompletions"] ?? 0); return { ...row, videoCompletionRate: starts > 0 ? Math.round((completions / starts) * 10000) / 100 : null, }; }); return { ...raw, enriched }; } - src/tools/analytics.ts:308-319 (schema)The getVideoAnalyticsSchema Zod schema defining input parameters: optional campaign_ids, optional ad_account_id, start_date (defaults to DEFAULT_START), end_date (defaults to DEFAULT_END), and time_granularity (defaults to 'ALL').
// ─── get-video-analytics ──────────────────────────────────────────────────── export const getVideoAnalyticsSchema = { campaign_ids: z .array(z.string()) .optional() .describe("Campaign numeric IDs or URNs to scope the report. Omit to report at account level."), ad_account_id: z.string().optional(), start_date: z.string().default(DEFAULT_START), end_date: z.string().default(DEFAULT_END), time_granularity: z.enum(TIME_GRANULARITIES).default("ALL"), }; - src/tools/analytics.ts:31-41 (helper)VIDEO_FIELDS constant defining the video-specific metric fields requested from the LinkedIn API: impressions, clicks, costInUsd, videoViews, videoFirstQuartileCompletions, videoMidpointCompletions, videoThirdQuartileCompletions, videoCompletions, videoStarts.
const VIDEO_FIELDS = [ "impressions", "clicks", "costInUsd", "videoViews", "videoFirstQuartileCompletions", "videoMidpointCompletions", "videoThirdQuartileCompletions", "videoCompletions", "videoStarts", ].join(","); - src/tools/analytics.ts:68-90 (helper)The buildAnalyticsUrl helper function that constructs the LinkedIn adAnalytics API URL with query parameters for pivot, timeGranularity, dateRange, fields, and either campaigns or accounts scope.
function buildAnalyticsUrl(opts: { pivot: string; timeGranularity: string; start: ReturnType<typeof resolveDate>; end: ReturnType<typeof resolveDate>; fields: string; campaignUrns?: string[]; accountUrn?: string; }): string { const qs: string[] = [ "q=statistics", `pivot=${opts.pivot}`, `timeGranularity=${opts.timeGranularity}`, `dateRange=${encodeURIComponent(dateRangeParam(opts.start, opts.end))}`, `fields=${opts.fields}`, ]; if (opts.campaignUrns && opts.campaignUrns.length > 0) { qs.push(`campaigns=${encodeURIComponent(listParam(opts.campaignUrns))}`); } else if (opts.accountUrn) { qs.push(`accounts=${encodeURIComponent(listParam([opts.accountUrn]))}`); } return `${BASE_URL}/adAnalytics?${qs.join("&")}`; } - src/index.ts:132-137 (registration)Tool registration using server.tool() with name 'li_get_video_analytics', description, schema, and handler that calls getVideoAnalytics and wraps the result with ok/err.
server.tool( "li_get_video_analytics", "Fetch video-specific performance metrics for LinkedIn campaigns, broken down by creative. Returns videoStarts, videoViews, videoFirstQuartileCompletions, videoMidpointCompletions, videoThirdQuartileCompletions, videoCompletions, plus a computed videoCompletionRate (completions / starts × 100). Use to evaluate video ad quality — high completion rates indicate compelling content; low rates signal drop-off. Scope to specific campaigns via campaign_ids or report at account level.", getVideoAnalyticsSchema, async (args) => { try { return ok(await getVideoAnalytics(args)); } catch (e) { return err(e); } } );