When you already know a prospect’s LinkedIn profile, you can use The Hog to inspect recent public posts they reacted to or commented on. This is useful when you want outreach to reference something timely instead of starting from a generic persona template.
This guide uses one profile as an example:
https://www.linkedin.com/in/paulonasc
What you will build
The script below:
- Fetches recent posts the profile reacted to.
- Fetches recent posts the profile commented on.
- Merges both signals by LinkedIn post.
- Prints concise outreach hook ideas you can review before using.
Use this to personalize legitimate business outreach from public activity. Always review the generated hooks, avoid sensitive inferences, and respect unsubscribe and outreach rules in your market.
Endpoints used
| Endpoint | What it returns |
|---|
POST /api/v1/platform/scrapers/linkedin/profile-reactions | Public posts a LinkedIn profile reacted to |
POST /api/v1/platform/scrapers/linkedin/profile-comments | Public posts a LinkedIn profile commented on |
Both endpoints accept:
profiles: LinkedIn /in/ profile URLs or public usernames
maxItems: maximum rows to return per profile
postedLimit: one of any, 24h, week, month, 3months, 6months, year
JavaScript example
Create linkedin-hooks.mjs:
const API_BASE_URL = "https://developer.thehog.ai";
const ACCESS_KEY = process.env.HOG_API_ACCESS_KEY;
const SECRET_KEY = process.env.HOG_API_SECRET_KEY;
const profile = process.argv[2] ?? "https://www.linkedin.com/in/paulonasc";
if (!ACCESS_KEY || !SECRET_KEY) {
throw new Error("Set HOG_API_ACCESS_KEY and HOG_API_SECRET_KEY");
}
async function post(path, body) {
const response = await fetch(`${API_BASE_URL}${path}`, {
method: "POST",
headers: {
"X-Access-Key": ACCESS_KEY,
"X-Secret-Key": SECRET_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (!response.ok) {
const text = await response.text();
throw new Error(`${path} failed with ${response.status}: ${text}`);
}
return response.json();
}
function postKey(item) {
return item.post?.postUrl ?? item.post?.postId ?? item.sourceUrl;
}
function summarizePost(post) {
const text = post?.text?.replace(/\s+/g, " ").trim();
if (!text) return "a recent LinkedIn post";
return text.length > 180 ? `${text.slice(0, 177)}...` : text;
}
function makeHooks(reactions, comments) {
const byPost = new Map();
for (const reaction of reactions) {
const key = postKey(reaction);
if (!key) continue;
const row = byPost.get(key) ?? {
post: reaction.post,
reactions: [],
comments: [],
};
row.reactions.push(reaction);
byPost.set(key, row);
}
for (const comment of comments) {
const key = postKey(comment);
if (!key) continue;
const row = byPost.get(key) ?? {
post: comment.post,
reactions: [],
comments: [],
};
row.comments.push(comment);
byPost.set(key, row);
}
return [...byPost.values()]
.sort((a, b) => b.comments.length - a.comments.length)
.slice(0, 10)
.map((row) => {
const author = row.post?.authorName ?? "someone in their network";
const postSummary = summarizePost(row.post);
const comment = row.comments[0]?.commentText;
return {
postUrl: row.post?.postUrl,
signal:
row.comments.length > 0
? `commented on ${author}'s post`
: `reacted to ${author}'s post`,
hook: comment
? `They commented: "${comment}". Reference the discussion around "${postSummary}".`
: `They reacted to a post about "${postSummary}". Use that topic as a light opener.`,
};
});
}
const request = {
profiles: [profile],
maxItems: 20,
postedLimit: "month",
};
const [reactionResponse, commentResponse] = await Promise.all([
post("/api/v1/platform/scrapers/linkedin/profile-reactions", request),
post("/api/v1/platform/scrapers/linkedin/profile-comments", request),
]);
const hooks = makeHooks(reactionResponse.data ?? [], commentResponse.data ?? []);
console.log(JSON.stringify({ profile, hooks }, null, 2));
Run it:
export HOG_API_ACCESS_KEY="ak_xxxxxxxxxxxxxxxx"
export HOG_API_SECRET_KEY="sk_xxxxxxxxxxxxxxxx"
node linkedin-hooks.mjs https://www.linkedin.com/in/paulonasc
Python example
Create linkedin_hooks.py:
import json
import os
import sys
import requests
API_BASE_URL = "https://developer.thehog.ai"
ACCESS_KEY = os.environ["HOG_API_ACCESS_KEY"]
SECRET_KEY = os.environ["HOG_API_SECRET_KEY"]
profile = sys.argv[1] if len(sys.argv) > 1 else "https://www.linkedin.com/in/paulonasc"
def post(path, body):
response = requests.post(
f"{API_BASE_URL}{path}",
headers={
"X-Access-Key": ACCESS_KEY,
"X-Secret-Key": SECRET_KEY,
"Content-Type": "application/json",
},
json=body,
timeout=120,
)
response.raise_for_status()
return response.json()
def post_key(item):
post = item.get("post") or {}
return post.get("postUrl") or post.get("postId") or item.get("sourceUrl")
def summarize_post(post):
text = " ".join((post.get("text") or "").split())
if not text:
return "a recent LinkedIn post"
return text[:177] + "..." if len(text) > 180 else text
request_body = {
"profiles": [profile],
"maxItems": 20,
"postedLimit": "month",
}
reactions = post(
"/api/v1/platform/scrapers/linkedin/profile-reactions",
request_body,
).get("data", [])
comments = post(
"/api/v1/platform/scrapers/linkedin/profile-comments",
request_body,
).get("data", [])
by_post = {}
for reaction in reactions:
key = post_key(reaction)
if not key:
continue
by_post.setdefault(key, {"post": reaction.get("post") or {}, "reactions": [], "comments": []})
by_post[key]["reactions"].append(reaction)
for comment in comments:
key = post_key(comment)
if not key:
continue
by_post.setdefault(key, {"post": comment.get("post") or {}, "reactions": [], "comments": []})
by_post[key]["comments"].append(comment)
hooks = []
for row in sorted(by_post.values(), key=lambda value: len(value["comments"]), reverse=True)[:10]:
post_body = row["post"]
author = post_body.get("authorName") or "someone in their network"
summary = summarize_post(post_body)
comment_text = row["comments"][0].get("commentText") if row["comments"] else None
hooks.append(
{
"postUrl": post_body.get("postUrl"),
"signal": (
f"commented on {author}'s post"
if row["comments"]
else f"reacted to {author}'s post"
),
"hook": (
f'They commented: "{comment_text}". Reference the discussion around "{summary}".'
if comment_text
else f'They reacted to a post about "{summary}". Use that topic as a light opener.'
),
}
)
print(json.dumps({"profile": profile, "hooks": hooks}, indent=2))
Run it:
export HOG_API_ACCESS_KEY="ak_xxxxxxxxxxxxxxxx"
export HOG_API_SECRET_KEY="sk_xxxxxxxxxxxxxxxx"
python linkedin_hooks.py https://www.linkedin.com/in/paulonasc
Example output
{
"profile": "https://www.linkedin.com/in/paulonasc",
"hooks": [
{
"postUrl": "https://www.linkedin.com/feed/update/urn:li:activity:123",
"signal": "commented on someone in their network's post",
"hook": "They commented: \"Great breakdown.\" Reference the discussion around \"a recent LinkedIn post\"."
},
{
"postUrl": "https://www.linkedin.com/feed/update/urn:li:activity:456",
"signal": "reacted to someone in their network's post",
"hook": "They reacted to a post about \"AI agents for sales workflows\". Use that topic as a light opener."
}
]
}
Production tips
- Keep
maxItems small for interactive workflows; increase it only for batch jobs.
- Prefer
postedLimit: "month" or shorter for timely hooks.
- Store the returned
postUrl with your CRM activity so reps can review the source context.
- Use comments first when available: they usually reveal stronger intent than a reaction alone.
- De-duplicate hooks across prospects before generating outreach sequences.