payload-posthog

Groups

$groups tagging on every capture, plus explicit group-property updates.

import { identifyGroup } from 'payload-posthog'

payloadPosthog({
  apiKey: process.env.POSTHOG_API_KEY!,
  groups: {
    mapper: ({ req }) =>
      req.user?.organizationId
        ? { groupType: 'organization', groupKey: req.user.organizationId }
        : undefined,
  },
})

// Elsewhere, when an org's properties actually change:
identifyGroup({ groupType: 'organization', groupKey: org.id, properties: { plan: org.plan } })

There's no default mapper — group structure (multi-tenant organizations, teams, accounts) is inherently application-specific.

Two separate mechanisms are involved, deliberately:

  • groups.mapper is a cheap, pure lookup used internally by capture to tag every event with $groups — it does not make a network call.
  • identifyGroup() actually sends/updates the group's properties in PostHog via groupIdentify(). Call it explicitly when those properties change (e.g. in an organization-settings hook) — not on every event, which would spam redundant updates.