How to Create an Analytics Module Provider
In this document, you’ll learn how to create an Analytics Module Provider and the methods you must implement in its main service.
Implementation Example#
As you implement your Analytics Module Provider, it can be useful to refer to an existing provider and how it's implemeted.
If you need to refer to an existing implementation as an example, check the PostHog Analytics Module Provider in the Medusa repository.
Create Module Provider Directory#
Start by creating a new directory for your module provider.
If you're creating the module provider in a Medusa application, create it under the src/modules
directory. For example, src/modules/my-analytics
.
If you're creating the module provider in a plugin, create it under the src/providers
directory. For example, src/providers/my-analytics
.
src/modules/my-analytics
directory as an example.2. Create the Analytics Module Provider's Service#
Create the file src/modules/my-analytics/service.ts
that holds the implementation of the module provider's main service. It must extend the AbstractAnalyticsProviderService
class imported from @medusajs/framework/utils
:
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
1import { Logger } from "@medusajs/framework/types"2import { AbstractAnalyticsProviderService } from "@medusajs/framework/utils"3 4type InjectedDependencies = {5 logger: Logger6}7 8type Options = {9 apiKey: string10}11 12class MyAnalyticsProviderService extends AbstractAnalyticsProviderService {13 protected logger_: Logger14 protected options_: Options15 static identifier = "my-analytics"16 // assuming you're initializing a client17 protected client18 19 constructor (20 { logger }: InjectedDependencies,21 options: Options22 ) {23 super()24 25 this.logger_ = logger26 this.options_ = options27 28 // assuming you're initializing a client29 this.client = new Client(options)30 }31}32 33export default MyAnalyticsProviderService
identifier#
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
identify#
This method identifies an actor or group in the third-party analytics provider. The Analytics Module
will use this method in its identify
method if your provider is configured in medusa-config.ts
.
Example
Parameters
The details of the actor or group.
Returns
Promise
Promise<void>shutdown#
This method is used to shutdown the analytics provider, and flush all data before shutting down.
This method is called by the Analytics Module when the Medusa application is shutting down.
Example
Returns
Promise
Promise<void>track#
This method tracks an event with the third-party analytics provider. The Analytics Module
will use this method in its track
method if your provider is configured in medusa-config.ts
.
You can send the event to the third-party provider based on its semantics.
Example
Parameters
The event's details.
Returns
Promise
Promise<void>3. Create Module Provider Definition File#
Create the file src/modules/my-analytics/index.ts
with the following content:
This exports the module provider's definition, indicating that the MyAnalyticsProviderService
is the module provider's service.
4. Use Module Provider#
To use your Analytics Module Provider, add it to the providers
array of the Analytics Module in medusa-config.ts
:
1module.exports = defineConfig({2 // ...3 modules: [4 {5 resolve: "@medusajs/medusa/analytics",6 options: {7 providers: [8 {9 // if module provider is in a plugin, use `plugin-name/providers/my-analytics`10 resolve: "./src/modules/my-analytics",11 id: "my-analytics",12 options: {13 // provider options...14 },15 },16 ],17 },18 },19 ]20})
5. Test it Out#
To test the module out, you'll track in your third-party provider when an order is placed.
You'll first create a workflow that tracks the order completion event. Then, you can execute the workflow in a subscriber that listens to the order.placed
event.
For example, create a workflow at src/workflows/track-order-placed.ts
with the following content:
1import { createWorkflow } from "@medusajs/framework/workflows-sdk"2import { createStep } from "@medusajs/framework/workflows-sdk"3import { Modules } from "@medusajs/framework/utils"4import { OrderDTO } from "@medusajs/framework/types"5 6type StepInput = {7 order: OrderDTO8}9 10const trackOrderCreatedStep = createStep(11 "track-order-created-step",12 async ({ order }: StepInput, { container }) => {13 const analyticsModuleService = container.resolve(Modules.ANALYTICS)14 15 await analyticsModuleService.track({16 event: "order_created",17 userId: order.customer_id,18 properties: {19 order_id: order.id,20 total: order.total,21 items: order.items.map((item) => ({22 variant_id: item.variant_id,23 product_id: item.product_id,24 quantity: item.quantity,25 })),26 customer_id: order.customer_id,27 },28 })29 }30)31 32type WorkflowInput = {33 order_id: string34}35 36export const trackOrderCreatedWorkflow = createWorkflow(37 "track-order-created-workflow",38 ({ order_id }: WorkflowInput) => {39 const { data: orders } = useQueryGraphStep({40 entity: "order",41 fields: [42 "*",43 "customer.*",44 "items.*"45 ],46 filters: {47 id: order_id,48 },49 })50 trackOrderCreatedStep({51 order: orders[0],52 })53 }54)
This workflow retrieves the order details using the useQueryGraphStep
and then tracks the order creation event using the trackOrderCreatedStep
.
In the step, you resolve the service of the Analytics Module from the Medusa container and use its track
method to track the event. This method will use the underlying provider configured (which is your provider, in this case) to track the event.
Next, create a subscriber at src/subscribers/order-placed.ts
with the following content:
1import type {2 SubscriberArgs,3 SubscriberConfig,4} from "@medusajs/framework"5import { trackOrderCreatedWorkflow } from "../workflows/track-order-created"6 7export default async function orderPlacedHandler({8 event: { data },9 container,10}: SubscriberArgs<{ id: string }>) {11 await trackOrderCreatedWorkflow(container).run({12 input: {13 order_id: data.id,14 },15 })16}17 18export const config: SubscriberConfig = {19 event: "order.placed",20}
This subscriber listens to the order.placed
event and executes the trackOrderCreatedWorkflow
workflow, passing the order ID as input.
You'll now track the order creation event whenever an order is placed in your Medusa application. You can test this out by placing an order and checking in your third-party provider if the event was tracked successfully.