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
@@ -1,6 +1,7 @@
|
||||
import { Link } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
ConfigModule,
|
||||
IAnalyticsModuleService,
|
||||
IApiKeyModuleService,
|
||||
IAuthModuleService,
|
||||
ICacheService,
|
||||
@@ -48,6 +49,7 @@ declare module "@medusajs/types" {
|
||||
[ContainerRegistrationKeys.REMOTE_QUERY]: RemoteQueryFunction
|
||||
[ContainerRegistrationKeys.QUERY]: Omit<RemoteQueryFunction, symbol>
|
||||
[ContainerRegistrationKeys.LOGGER]: Logger
|
||||
[Modules.ANALYTICS]: IAnalyticsModuleService
|
||||
[Modules.AUTH]: IAuthModuleService
|
||||
[Modules.CACHE]: ICacheService
|
||||
[Modules.CART]: ICartModuleService
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from "./mutations"
|
||||
export * from "./service"
|
||||
export * from "./provider"
|
||||
export * from "./providers"
|
||||
@@ -0,0 +1,39 @@
|
||||
export interface TrackAnalyticsEventDTO {
|
||||
/**
|
||||
* The event name
|
||||
*/
|
||||
event: string
|
||||
/**
|
||||
* The actor of the event, if there is any
|
||||
*/
|
||||
actor_id?: string
|
||||
/**
|
||||
* The group that the event is for, such as an organization or team.
|
||||
* The "type" defines the name of the group (eg. "organization"), and the "id" is the id of the group.
|
||||
*/
|
||||
group?: {
|
||||
type?: string
|
||||
id?: string
|
||||
}
|
||||
/**
|
||||
* The properties of the event. The format and content depends on the provider.
|
||||
*/
|
||||
properties?: Record<string, any>
|
||||
}
|
||||
|
||||
export interface IdentifyActorDTO {
|
||||
actor_id: string
|
||||
properties?: Record<string, any>
|
||||
}
|
||||
|
||||
export interface IdentifyGroupDTO {
|
||||
group: {
|
||||
type: string
|
||||
id: string
|
||||
}
|
||||
// When identifying a group, the actor can potentially be passed as well as metadata.
|
||||
actor_id?: string
|
||||
properties?: Record<string, any>
|
||||
}
|
||||
// Either actor_id or group must be provided. Depending on the provided identifier, the properties will be set for the actor or group.
|
||||
export type IdentifyAnalyticsEventDTO = IdentifyActorDTO | IdentifyGroupDTO
|
||||
@@ -0,0 +1,33 @@
|
||||
import { IdentifyAnalyticsEventDTO, TrackAnalyticsEventDTO } from "./mutations"
|
||||
|
||||
export type ProviderTrackAnalyticsEventDTO = TrackAnalyticsEventDTO
|
||||
|
||||
export type ProviderIdentifyAnalyticsEventDTO = IdentifyAnalyticsEventDTO
|
||||
|
||||
export interface IAnalyticsProvider {
|
||||
/**
|
||||
* This method is used to track an event in the analytics provider
|
||||
*
|
||||
* @param {ProviderTrackAnalyticsEventDTO} data - The data for the event.
|
||||
* @returns {Promise<void>} Resolves when the event is tracked successfully.
|
||||
*
|
||||
*/
|
||||
track(data: ProviderTrackAnalyticsEventDTO): Promise<void>
|
||||
|
||||
/**
|
||||
* This method is used to identify an actor or group in the analytics provider
|
||||
*
|
||||
* @param {ProviderIdentifyAnalyticsEventDTO} data - The data for the actor or group..
|
||||
* @returns {Promise<void>} Resolves when the event is tracked successfully.
|
||||
*
|
||||
*/
|
||||
identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void>
|
||||
|
||||
/**
|
||||
* This method is used to shutdown the analytics provider, and flush all data before shutting down.
|
||||
*
|
||||
* @returns {Promise<void>} Resolves when the provider is shutdown successfully.
|
||||
*
|
||||
*/
|
||||
shutdown?(): Promise<void>
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from "./posthog"
|
||||
export * from "./local"
|
||||
@@ -0,0 +1 @@
|
||||
export interface LocalAnalyticsServiceOptions {}
|
||||
@@ -0,0 +1,10 @@
|
||||
export interface PosthogAnalyticsServiceOptions {
|
||||
/**
|
||||
* The key for the posthog events
|
||||
*/
|
||||
posthogEventsKey: string
|
||||
/**
|
||||
* The endpoint for the posthog server
|
||||
*/
|
||||
posthogHost: string
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { IModuleService } from "../modules-sdk"
|
||||
import { IdentifyAnalyticsEventDTO, TrackAnalyticsEventDTO } from "./mutations"
|
||||
import { IAnalyticsProvider } from "./provider"
|
||||
|
||||
export interface IAnalyticsModuleService extends IModuleService {
|
||||
/**
|
||||
* Returns a reference to the analytics provider in use
|
||||
*/
|
||||
getProvider(): IAnalyticsProvider
|
||||
|
||||
/**
|
||||
* This method tracks an event in the analytics provider
|
||||
*
|
||||
* @param {TrackAnalyticsEventDTO} data - The data for the event.
|
||||
* @returns {Promise<void>} Resolves when the event is tracked successfully.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* await analyticsModuleService.track({
|
||||
* event: "product_viewed",
|
||||
* properties: {
|
||||
* product_id: "123",
|
||||
* product_name: "Product Name"
|
||||
* }
|
||||
* })
|
||||
*/
|
||||
track(data: TrackAnalyticsEventDTO): Promise<void>
|
||||
|
||||
/**
|
||||
* This method identifies an actor or group in the analytics provider
|
||||
*
|
||||
* @param {IdentifyAnalyticsEventDTO} data - The data for the actor or group.
|
||||
* @returns {Promise<void>} Resolves when the actor or group is identified successfully.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* await analyticsModuleService.identify({
|
||||
* actor_id: "123",
|
||||
* properties: {
|
||||
* name: "John Doe"
|
||||
* }
|
||||
* })
|
||||
*/
|
||||
identify(data: IdentifyAnalyticsEventDTO): Promise<void>
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
export * as AdminTypes from "./admin"
|
||||
export * as AnalyticsTypes from "./analytics"
|
||||
export * as ApiKeyTypes from "./api-key"
|
||||
export * as AuthTypes from "./auth"
|
||||
export * as CacheTypes from "./cache"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from "./address"
|
||||
export * from "./admin"
|
||||
export * from "./analytics"
|
||||
export * from "./api-key"
|
||||
export * from "./auth"
|
||||
export * from "./bundles"
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import {
|
||||
IAnalyticsProvider,
|
||||
ProviderIdentifyAnalyticsEventDTO,
|
||||
ProviderTrackAnalyticsEventDTO,
|
||||
} from "@medusajs/types"
|
||||
|
||||
/**
|
||||
* ### constructor
|
||||
*
|
||||
* The constructor allows you to access resources from the module's container using the first parameter,
|
||||
* and the module's options using the second parameter.
|
||||
*
|
||||
* If you're creating a client or establishing a connection with a third-party service, do it in the constructor.
|
||||
*
|
||||
* #### Example
|
||||
*
|
||||
* ```ts
|
||||
* import { Logger } from "@medusajs/framework/types"
|
||||
* import { AbstractAnalyticsProviderService } from "@medusajs/framework/utils"
|
||||
*
|
||||
* type InjectedDependencies = {
|
||||
* logger: Logger
|
||||
* }
|
||||
*
|
||||
* type Options = {
|
||||
* apiKey: string
|
||||
* }
|
||||
*
|
||||
* class MyAnalyticsProviderService extends AbstractAnalyticsProviderService {
|
||||
* protected logger_: Logger
|
||||
* protected options_: Options
|
||||
* static identifier = "my-analytics"
|
||||
* // assuming you're initializing a client
|
||||
* protected client
|
||||
*
|
||||
* constructor (
|
||||
* { logger }: InjectedDependencies,
|
||||
* options: Options
|
||||
* ) {
|
||||
* super()
|
||||
*
|
||||
* this.logger_ = logger
|
||||
* this.options_ = options
|
||||
*
|
||||
* // assuming you're initializing a client
|
||||
* this.client = new Client(options)
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* export default MyAnalyticsProviderService
|
||||
* ```
|
||||
*/
|
||||
export class AbstractAnalyticsProviderService implements IAnalyticsProvider {
|
||||
/**
|
||||
* Each analytics provider has a unique ID used to identify it. The provider's ID
|
||||
* will be stored as `aly_{identifier}_{id}`, where `{id}` is the provider's `id`
|
||||
* property in the `medusa-config.ts`.
|
||||
*
|
||||
* @example
|
||||
* class MyAnalyticsProviderService extends AbstractAnalyticsProviderService {
|
||||
* static identifier = "my-analytics"
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
static identifier: string
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
getIdentifier() {
|
||||
return (this.constructor as any).identifier
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tracks an event using your provider's semantics
|
||||
*
|
||||
* This method will be used when tracking events to third-party providers.
|
||||
*
|
||||
* @param {ProviderTrackAnalyticsEventDTO} data - The data for the event.
|
||||
* @returns {Promise<void>} Resolves when the event is tracked successfully.
|
||||
*
|
||||
* @example
|
||||
* class MyAnalyticsProviderService extends AbstractAnalyticsProviderService {
|
||||
* // ...
|
||||
* async track(
|
||||
* data: ProviderTrackAnalyticsEventDTO
|
||||
* ): Promise<void> {
|
||||
* // track event to third-party provider
|
||||
* // or using custom logic
|
||||
* // for example:
|
||||
* this.client.track(data)
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
async track(data: ProviderTrackAnalyticsEventDTO): Promise<void> {
|
||||
throw Error("track must be overridden by the child class")
|
||||
}
|
||||
|
||||
/**
|
||||
* This method identifies an actor or group in the analytics provider
|
||||
*
|
||||
* @param {ProviderIdentifyAnalyticsEventDTO} data - The data for the actor or group.
|
||||
* @returns {Promise<void>} Resolves when the actor or group is identified successfully.
|
||||
*
|
||||
* @example
|
||||
* class MyAnalyticsProviderService extends AbstractAnalyticsProviderService {
|
||||
* // ...
|
||||
* async identify(
|
||||
* data: ProviderIdentifyAnalyticsEventDTO
|
||||
* ): Promise<void> {
|
||||
* // identify actor or group in the analytics provider
|
||||
* // or using custom logic
|
||||
* // for example:
|
||||
* this.client.identify(data)
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
async identify(data: ProviderIdentifyAnalyticsEventDTO): Promise<void> {
|
||||
throw Error("identify must be overridden by the child class")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./abstract-analytics-provider"
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from "./api-key"
|
||||
export * from "./analytics"
|
||||
export * from "./auth"
|
||||
export * from "./bundles"
|
||||
export * from "./common"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export const Modules = {
|
||||
ANALYTICS: "analytics",
|
||||
AUTH: "auth",
|
||||
CACHE: "cache",
|
||||
CART: "cart",
|
||||
@@ -28,6 +29,7 @@ export const Modules = {
|
||||
} as const
|
||||
|
||||
export const MODULE_PACKAGE_NAMES = {
|
||||
[Modules.ANALYTICS]: "@medusajs/medusa/analytics",
|
||||
[Modules.AUTH]: "@medusajs/medusa/auth",
|
||||
[Modules.CACHE]: "@medusajs/medusa/cache-inmemory",
|
||||
[Modules.CART]: "@medusajs/medusa/cart",
|
||||
|
||||
Reference in New Issue
Block a user