Avatar

@ianvph

1 like7 public vals
Joined August 24, 2023
Technical Content Marketer @ PostHog

A GitHub webhook handler to capture stars in PostHog

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { capturePostHogEvent } from "https://esm.town/v/ianvph/capturePostHogEvent";
export default async function(req: Request): Promise<Response> {
if (req.method !== "POST") {
return Response.json({ ok: "only post request" });
}
const webhookPayload = await req.json();
if (webhookPayload.action !== "created") {
return Response.json({ ok: "only stars" });
}
console.log(webhookPayload);
const eventProperties = {
repository: webhookPayload.repository.full_name,
starred_at: webhookPayload.starred_at,
user: webhookPayload.sender.login,
user_id: webhookPayload.sender.id,
user_url: webhookPayload.sender.url,
avatar: webhookPayload.sender.avatar_url,
};
capturePostHogEvent(
Deno.env.get("phProjectAPIKey"),
webhookPayload.sender.login,
"GitHub Star",
eventProperties,
);
return Response.json({
ok: true,
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import process from "node:process";
import { capturePostHogEvent } from "https://esm.town/v/ianvph/capturePostHogEvent";
export async function captureCalendlyWebhook(req: Request) {
let reqJson = await req.json();
console.log(reqJson);
const eventType = reqJson["event"];
let eventName = "calendly_event";
if (eventType === "invitee.created") {
eventName = "meeting_scheduled";
}
else if (eventType === "invitee.canceled") {
eventName = "meeting_cancelled";
}
const user = reqJson["payload"]["email"];
const name = reqJson["payload"]["name"];
const properties = {
email: user,
event_type: eventType,
name: name,
};
capturePostHogEvent(
process.env.phProjectAPIKey,
user,
eventName,
properties,
);
return Response.json({ ok: true });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export async function capturePostHogEvent(
key: string,
distinct_id: string,
event_name: string,
properties: object = {},
host: string = "https://app.posthog.com",
) {
const { PostHog } = await import("npm:posthog-node");
const client = new PostHog(key, {
host: host,
});
client.capture({
distinctId: distinct_id,
event: event_name,
properties: properties,
});
client.on("error", (err) => {
console.log(err);
});
// flush events because this is short-lived process
await client.shutdown();
return "Event captured";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import { fetch } from "https://esm.town/v/std/fetch";
import { set } from "https://esm.town/v/std/set?v=11";
import { postHogAPICapture } from "https://esm.town/v/ianvph/postHogAPICapture";
import { email } from "https://esm.town/v/ianvph/email";
import { phProjectAPIKey } from "https://esm.town/v/ianvph/phProjectAPIKey";
import { newestStatusGuid } from "https://esm.town/v/ianvph/newestStatusGuid";
import { parseXML } from "https://esm.town/v/stevekrouse/parseXML?v=1";
export async function posthogStatusTracker() {
// gets newest status update from rss feed
const statusRSSLink = "https://status.posthog.com/history.rss";
const response = await fetch(statusRSSLink);
const newestEntry =
(await parseXML(await response.text())).rss.channel
.item[0];
// checks if different from last status captured
console.log(newestEntry);
if (newestEntry.guid == newestStatusGuid) {
return "old status";
}
// captures event to posthog if so
const properties = {
title: newestEntry.title,
published_date: newestEntry.pubDate,
link: newestEntry.link,
};
const captureData = {
key: phProjectAPIKey,
event: "posthog status update",
properties: properties,
distinct_id: email,
};
postHogAPICapture(captureData);
await set("newestStatusGuid", newestEntry.guid);
return "posthog status update captured";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import { fetch } from "https://esm.town/v/std/fetch";
import { set } from "https://esm.town/v/std/set?v=11";
import { postHogAPICapture } from "https://esm.town/v/ianvph/postHogAPICapture";
import { email } from "https://esm.town/v/ianvph/email";
import { phProjectAPIKey } from "https://esm.town/v/ianvph/phProjectAPIKey";
import { newestBlogLink } from "https://esm.town/v/ianvph/newestBlogLink";
import { parseXML } from "https://esm.town/v/stevekrouse/parseXML?v=1";
export async function blogRSSTracker() {
// gets newest blog from rss feed
const blogRSSLink = "https://posthog.com/rss.xml";
const response = await fetch(blogRSSLink);
const newestEntry =
(await parseXML(await response.text())).rss.channel
.item[0];
// checks if different from last blog captured
if (newestEntry.link == newestBlogLink) {
return "old blog";
}
// captures event to posthog if so
const properties = {
title: newestEntry.title,
published_date: newestEntry.pubDate,
author: newestEntry["dc:creator"],
link: newestEntry.link,
};
const captureData = {
key: phProjectAPIKey,
event: "new blog published",
properties: properties,
distinct_id: email,
};
postHogAPICapture(captureData);
await set("newestBlogLink", newestEntry.link);
return "new blog captured";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import { fetch } from "https://esm.town/v/std/fetch";
import { set } from "https://esm.town/v/std/set?v=11";
import { postHogAPICapture } from "https://esm.town/v/ianvph/postHogAPICapture";
import { email } from "https://esm.town/v/ianvph/email";
import { phProjectAPIKey } from "https://esm.town/v/ianvph/phProjectAPIKey";
import { newestReleaseId } from "https://esm.town/v/ianvph/newestReleaseId";
import { parseXML } from "https://esm.town/v/stevekrouse/parseXML?v=1";
export async function gitHubReleaseTracker() {
// gets newest release from github
const githubProject = "https://github.com/posthog/posthog";
const response = await fetch(`${githubProject}/releases.atom`);
const newestEntry =
(await parseXML(await response.text())).feed
.entry[0];
// checks if different from last release
if (newestEntry.id == newestReleaseId) {
return "old release";
}
// captures event to posthog if so
const properties = {
title: newestEntry.title,
release_date: newestEntry.updated,
author: newestEntry.author.name,
};
const captureData = {
key: phProjectAPIKey,
event: "new release",
properties: properties,
distinct_id: email,
};
postHogAPICapture(captureData);
await set("newestReleaseId", newestEntry.id);
return "new release captured";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { fetch } from "https://esm.town/v/std/fetch";
export async function postHogAPICapture({ key, event, properties, distinct_id }: {
key: string;
event: string;
properties: object;
distinct_id: string;
}) {
const body = {
"api_key": key,
"event": event,
"properties": properties,
"distinct_id": distinct_id,
};
let result = await fetch("https://app.posthog.com/capture/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}).then((r) => r.json());
if (result.error) {
throw new Error("PH error " + result.error.message);
}
else {
return result;
}
}
Next