feat: Add an analytics module and local and posthog providers (#12505)
* feat: Add an analytics module and local and posthog providers * fix: Add tests and wire up in missing places * fix: Address feedback and add missing module typing * fix: Address feedback and add missing module typing --------- Co-authored-by: Adrien de Peretti <adrien.deperetti@gmail.com> Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
co-authored by
Adrien de Peretti
Oli Juhl
parent
52bd9f9a53
commit
b9a51e217d
@@ -0,0 +1 @@
|
||||
# @medusajs/analytics-local
|
||||
@@ -0,0 +1,6 @@
|
||||
const defineJestConfig = require("../../../../define_jest_config")
|
||||
module.exports = defineJestConfig({
|
||||
moduleNameMapper: {
|
||||
"^@services": "<rootDir>/src/services",
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "@medusajs/analytics-local",
|
||||
"version": "2.8.2",
|
||||
"description": "Local analytics provider for Medusa",
|
||||
"main": "dist/index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/medusajs/medusa",
|
||||
"directory": "packages/modules/providers/analytics-local"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"!dist/**/__tests__",
|
||||
"!dist/**/__mocks__",
|
||||
"!dist/**/__fixtures__"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"author": "Medusa",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest --passWithNoTests src",
|
||||
"build": "rimraf dist && tsc --build ./tsconfig.json",
|
||||
"watch": "tsc --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@medusajs/framework": "2.8.2",
|
||||
"@swc/core": "^1.7.28",
|
||||
"@swc/jest": "^0.2.36",
|
||||
"jest": "^29.7.0",
|
||||
"rimraf": "^5.0.1",
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@medusajs/framework": "2.8.2"
|
||||
},
|
||||
"keywords": [
|
||||
"medusa-plugin",
|
||||
"medusa-plugin-analytics"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ModuleProvider, Modules } from "@medusajs/framework/utils"
|
||||
import { LocalAnalyticsService } from "./services/local-analytics"
|
||||
|
||||
const services = [LocalAnalyticsService]
|
||||
|
||||
export default ModuleProvider(Modules.ANALYTICS, {
|
||||
services,
|
||||
})
|
||||
@@ -0,0 +1,44 @@
|
||||
import {
|
||||
LocalAnalyticsServiceOptions,
|
||||
Logger,
|
||||
ProviderIdentifyAnalyticsEventDTO,
|
||||
ProviderTrackAnalyticsEventDTO,
|
||||
} from "@medusajs/framework/types"
|
||||
import { AbstractAnalyticsProviderService } from "@medusajs/framework/utils"
|
||||
|
||||
type InjectedDependencies = {
|
||||
logger: Logger
|
||||
}
|
||||
|
||||
export class LocalAnalyticsService extends AbstractAnalyticsProviderService {
|
||||
static identifier = "analytics-local"
|
||||
protected config_: LocalAnalyticsServiceOptions
|
||||
protected logger_: Logger
|
||||
|
||||
constructor(
|
||||
{ logger }: InjectedDependencies,
|
||||
options: LocalAnalyticsServiceOptions
|
||||
) {
|
||||
super()
|
||||
this.config_ = options
|
||||
this.logger_ = logger
|
||||
}
|
||||
|
||||
async track(data: ProviderTrackAnalyticsEventDTO): Promise<void> {
|
||||
this.logger_.debug(
|
||||
`Tracking event: '${data.event}', actor_id: '${
|
||||
data.actor_id ?? "-"
|
||||
}', group: '${data.group?.id ?? "-"}', properties: '${JSON.stringify(
|
||||
data.properties
|
||||
)}'`
|
||||
)
|
||||
}
|
||||
|
||||
async identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void> {
|
||||
this.logger_.debug(
|
||||
`Identifying user: '${data.actor_id ?? "-"}', group: '${
|
||||
"group" in data ? data.group.id : "-"
|
||||
}', properties: '${JSON.stringify(data.properties)}'`
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../../../_tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@services": ["./src/services"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
# @medusajs/analytics-posthog
|
||||
@@ -0,0 +1,6 @@
|
||||
const defineJestConfig = require("../../../../define_jest_config")
|
||||
module.exports = defineJestConfig({
|
||||
moduleNameMapper: {
|
||||
"^@services": "<rootDir>/src/services",
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "@medusajs/analytics-posthog",
|
||||
"version": "2.8.2",
|
||||
"description": "Posthog analytics provider for Medusa",
|
||||
"main": "dist/index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/medusajs/medusa",
|
||||
"directory": "packages/modules/providers/analytics-posthog"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"!dist/**/__tests__",
|
||||
"!dist/**/__mocks__",
|
||||
"!dist/**/__fixtures__"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"author": "Medusa",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest --passWithNoTests src",
|
||||
"build": "rimraf dist && tsc --build ./tsconfig.json",
|
||||
"watch": "tsc --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@medusajs/framework": "2.8.2",
|
||||
"@swc/core": "^1.7.28",
|
||||
"@swc/jest": "^0.2.36",
|
||||
"jest": "^29.7.0",
|
||||
"posthog-node": "^4.17.1",
|
||||
"rimraf": "^5.0.1",
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@medusajs/framework": "2.8.2"
|
||||
},
|
||||
"keywords": [
|
||||
"medusa-plugin",
|
||||
"medusa-plugin-analytics"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ModuleProvider, Modules } from "@medusajs/framework/utils"
|
||||
import { PosthogAnalyticsService } from "./services/posthog-analytics"
|
||||
|
||||
const services = [PosthogAnalyticsService]
|
||||
|
||||
export default ModuleProvider(Modules.ANALYTICS, {
|
||||
services,
|
||||
})
|
||||
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
PosthogAnalyticsServiceOptions,
|
||||
Logger,
|
||||
ProviderIdentifyAnalyticsEventDTO,
|
||||
ProviderTrackAnalyticsEventDTO,
|
||||
} from "@medusajs/framework/types"
|
||||
import { PostHog } from "posthog-node"
|
||||
import { AbstractAnalyticsProviderService } from "@medusajs/framework/utils"
|
||||
|
||||
type InjectedDependencies = {
|
||||
logger: Logger
|
||||
}
|
||||
|
||||
export class PosthogAnalyticsService extends AbstractAnalyticsProviderService {
|
||||
static identifier = "analytics-posthog"
|
||||
protected config_: PosthogAnalyticsServiceOptions
|
||||
protected logger_: Logger
|
||||
protected client_: PostHog
|
||||
|
||||
constructor(
|
||||
{ logger }: InjectedDependencies,
|
||||
options: PosthogAnalyticsServiceOptions
|
||||
) {
|
||||
super()
|
||||
this.config_ = options
|
||||
this.logger_ = logger
|
||||
|
||||
if (!options.posthogEventsKey) {
|
||||
throw new Error("Posthog API key is not set, but is required")
|
||||
}
|
||||
|
||||
this.client_ = new PostHog(options.posthogEventsKey, {
|
||||
host: options.posthogHost || "https://eu.i.posthog.com",
|
||||
})
|
||||
}
|
||||
|
||||
async track(data: ProviderTrackAnalyticsEventDTO): Promise<void> {
|
||||
if (!data.event) {
|
||||
throw new Error(
|
||||
"Event name is required when tracking an event with Posthog"
|
||||
)
|
||||
}
|
||||
|
||||
if (!data.actor_id) {
|
||||
throw new Error(
|
||||
"Actor ID is required when tracking an event with Posthog"
|
||||
)
|
||||
}
|
||||
|
||||
if (data.group?.id && !data.group?.type) {
|
||||
throw new Error(
|
||||
"Group type is required if passing group id when tracking an event with Posthog"
|
||||
)
|
||||
}
|
||||
|
||||
this.client_.capture({
|
||||
event: data.event,
|
||||
distinctId: data.actor_id,
|
||||
properties: data.properties,
|
||||
groups: data.group?.id
|
||||
? { [data.group.type!]: data.group.id }
|
||||
: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
async identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void> {
|
||||
if ("group" in data) {
|
||||
this.client_.groupIdentify({
|
||||
groupKey: data.group.id!,
|
||||
groupType: data.group.type!,
|
||||
properties: data.properties,
|
||||
distinctId: data.actor_id,
|
||||
})
|
||||
} else if (data.actor_id) {
|
||||
this.client_.identify({
|
||||
distinctId: data.actor_id,
|
||||
properties: data.properties,
|
||||
})
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
"Actor or group is required when identifying an entity with Posthog"
|
||||
)
|
||||
}
|
||||
|
||||
async shutdown() {
|
||||
await this.client_.shutdown()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../../../_tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@services": ["./src/services"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user