curl --request GET \
--url https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body[
{
"id": "550e8400-e29b-41d4-a716-446655440600",
"url": "https://www.linkedin.com/feed/update/urn:li:share:7123456789012345678",
"commentary": "Excited to share our latest product update! š\n\nAfter months of development, we're launching three new features that will transform how you work:\n\nā
Feature A\nā
Feature B\nā
Feature C\n\nLearn more in the comments š",
"type": "Text",
"publishedAt": "2024-12-10T14:00:00.000Z",
"likeCount": 245,
"commentCount": 32,
"shareCount": 18,
"clickCount": 156,
"linkClickCount": null,
"profileViewFromContentCount": null,
"premiumCtaClickCount": null,
"followerGainedFromContentCount": null,
"saveCount": 41,
"sendCount": 12,
"impressionCount": 12500,
"engagement": 0.036,
"emv": 375,
"ordinalPost": {
"id": "44444444-4444-4444-a444-444444444444",
"title": "LinkedIn Ordinal Post",
"labels": [
{
"name": "Product",
"labelId": "55555555-5555-4555-a555-555555555555"
}
],
"campaign": {
"id": "66666666-6666-4666-a666-666666666666",
"name": "Launch Campaign"
}
}
},
{
"id": "550e8400-e29b-41d4-a716-446655440601",
"url": "https://www.linkedin.com/feed/update/urn:li:share:7123456789012345679",
"commentary": "5 lessons learned from scaling our startup from 0 to 10k users š\n\nWatch the full breakdown:",
"type": "Video",
"publishedAt": "2024-12-05T09:30:00.000Z",
"likeCount": 892,
"commentCount": 67,
"shareCount": 134,
"clickCount": null,
"linkClickCount": 312,
"profileViewFromContentCount": 87,
"premiumCtaClickCount": 5,
"followerGainedFromContentCount": 24,
"saveCount": 156,
"sendCount": 48,
"impressionCount": 28900,
"engagement": 0.052,
"emv": 867,
"videoViewCount": 15420,
"videoViewerCount": 12800,
"videoWatchTimeSeconds": 82340,
"ordinalPost": null
}
]{
"code": "UNAUTHORIZED",
"message": "Invalid or unauthorized API key"
}{
"code": "FORBIDDEN",
"message": "Engagement profiles cannot be used for analytics"
}{
"code": "NOT_FOUND",
"message": "Post not found or does not belong to this workspace"
}LinkedIn post analytics
Retrieve post analytics for a LinkedIn profile within a date range. When a post was published from Ordinal, the response includes an ordinalPost object with the linked postās id, title, labels, and campaign.
Click metrics by profile type:
- Personal (member) profiles return
linkClickCount,profileViewFromContentCount,premiumCtaClickCount, andfollowerGainedFromContentCount.clickCountis always null. - Organization (company page) profiles return
clickCountfor total post clicks. The four member-only fields above are always null.
Personal profiles also include saveCount (times the post was saved) and sendCount (times the post was sent via DM). Posts with type Video also include videoViewCount, videoViewerCount, and videoWatchTimeSeconds; these fields are null for non-video posts and for video posts that have not yet been synced.
curl --request GET \
--url https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.tryordinal.com/api/v1/analytics/linkedin/{profileId}/posts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body[
{
"id": "550e8400-e29b-41d4-a716-446655440600",
"url": "https://www.linkedin.com/feed/update/urn:li:share:7123456789012345678",
"commentary": "Excited to share our latest product update! š\n\nAfter months of development, we're launching three new features that will transform how you work:\n\nā
Feature A\nā
Feature B\nā
Feature C\n\nLearn more in the comments š",
"type": "Text",
"publishedAt": "2024-12-10T14:00:00.000Z",
"likeCount": 245,
"commentCount": 32,
"shareCount": 18,
"clickCount": 156,
"linkClickCount": null,
"profileViewFromContentCount": null,
"premiumCtaClickCount": null,
"followerGainedFromContentCount": null,
"saveCount": 41,
"sendCount": 12,
"impressionCount": 12500,
"engagement": 0.036,
"emv": 375,
"ordinalPost": {
"id": "44444444-4444-4444-a444-444444444444",
"title": "LinkedIn Ordinal Post",
"labels": [
{
"name": "Product",
"labelId": "55555555-5555-4555-a555-555555555555"
}
],
"campaign": {
"id": "66666666-6666-4666-a666-666666666666",
"name": "Launch Campaign"
}
}
},
{
"id": "550e8400-e29b-41d4-a716-446655440601",
"url": "https://www.linkedin.com/feed/update/urn:li:share:7123456789012345679",
"commentary": "5 lessons learned from scaling our startup from 0 to 10k users š\n\nWatch the full breakdown:",
"type": "Video",
"publishedAt": "2024-12-05T09:30:00.000Z",
"likeCount": 892,
"commentCount": 67,
"shareCount": 134,
"clickCount": null,
"linkClickCount": 312,
"profileViewFromContentCount": 87,
"premiumCtaClickCount": 5,
"followerGainedFromContentCount": 24,
"saveCount": 156,
"sendCount": 48,
"impressionCount": 28900,
"engagement": 0.052,
"emv": 867,
"videoViewCount": 15420,
"videoViewerCount": 12800,
"videoWatchTimeSeconds": 82340,
"ordinalPost": null
}
]{
"code": "UNAUTHORIZED",
"message": "Invalid or unauthorized API key"
}{
"code": "FORBIDDEN",
"message": "Engagement profiles cannot be used for analytics"
}{
"code": "NOT_FOUND",
"message": "Post not found or does not belong to this workspace"
}Authorizations
API key authentication. Generate an API key from your workspace settings.
Path Parameters
LinkedIn profile ID (UUID)
Query Parameters
Start date for analytics (defaults to 30 days ago)
End date for analytics (defaults to today)
Response
LinkedIn post analytics
LinkedIn post URL
The type of LinkedIn post
Text, Article, Image, Video, Poll, Celebration, Job, Event, Document, Repost, QuotePost, MultiImage Total post clicks. Available for organization (company page) profiles only; null for personal profiles.
Clicks on links embedded in the post. Available for personal LinkedIn profiles only; null for organization profiles.
Profile views driven by this post. Available for personal LinkedIn profiles only; null for organization profiles.
Clicks on LinkedIn Premium CTAs (for example, Book an appointment) attached to the post. Available for personal LinkedIn profiles only; null for organization profiles.
New followers attributed to this post. Available for personal LinkedIn profiles only; null for organization profiles.
Times the post was saved to view later. Available for personal LinkedIn profiles only.
Times the post was sent via direct message. Available for personal LinkedIn profiles only.
Engagement rate (total engagements / impressions), typically between 0 and 1
Earned Media Value calculated as (impressionCount / 1000) * CPM
Total views on a video post. Only populated for posts with type Video; null for non-video posts and video posts that have not yet been synced.
Unique viewers of a video post. Only populated for posts with type Video; null for non-video posts and video posts that have not yet been synced.
Total watch time across all viewers, in whole seconds. Only populated for posts with type Video; null for non-video posts and video posts that have not yet been synced.
Linked Ordinal post when this external post was published from Ordinal, null otherwise
Show child attributes
Show child attributes
Was this page helpful?