diff --git a/apps/console/app/root.tsx b/apps/console/app/root.tsx index 89d33df100..f3d978db6a 100644 --- a/apps/console/app/root.tsx +++ b/apps/console/app/root.tsx @@ -255,7 +255,6 @@ export default function App() { api_host: loaderData.ENV.POSTHOG_PROXY_HOST, autocapture: false, }) - posthog?.identify(identityURN) } catch (ex) { console.error(ex) diff --git a/apps/console/app/routes/__layout/billing/webhook.tsx b/apps/console/app/routes/__layout/billing/webhook.tsx index 5444e5fc6b..c294a8c7f1 100644 --- a/apps/console/app/routes/__layout/billing/webhook.tsx +++ b/apps/console/app/routes/__layout/billing/webhook.tsx @@ -208,22 +208,7 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( ) await createAnalyticsEvent({ - eventName: 'purchase', - apiKey: context.env.POSTHOG_API_KEY, - distinctId: customerDataSuccess.metadata.identityURN, - properties: { - plans: purchasedItems.map((item) => ({ - quantity: item.quantity, - name: products.find( - (product) => product?.id === item?.productID - )!.name, - type: ServicePlanType.PRO, - })), - }, - }) - - await createAnalyticsEvent({ - eventName: 'purchase', + eventName: 'identity_purchased_entitlement', apiKey: context.env.POSTHOG_API_KEY, distinctId: customerDataSuccess.metadata.identityURN, properties: { diff --git a/apps/console/app/routes/__layout/spuorg/$groupID/invite.tsx b/apps/console/app/routes/__layout/spuorg/$groupID/invite.tsx index 04c944ce24..70486e074e 100644 --- a/apps/console/app/routes/__layout/spuorg/$groupID/invite.tsx +++ b/apps/console/app/routes/__layout/spuorg/$groupID/invite.tsx @@ -1,24 +1,20 @@ import { generateTraceContextHeaders } from '@proofzero/platform-middleware/trace' import { getRollupReqFunctionErrorWrapper } from '@proofzero/utils/errors' -import { ActionFunction, json } from '@remix-run/cloudflare' +import { type ActionFunction, json } from '@remix-run/cloudflare' import { requireJWT } from '~/utilities/session.server' import createCoreClient from '@proofzero/platform-clients/core' -import { - getAuthzHeaderConditionallyFromToken, - parseJwt, -} from '@proofzero/utils' +import { getAuthzHeaderConditionallyFromToken } from '@proofzero/utils' import { BadRequestError } from '@proofzero/errors' -import { +import type { CryptoAccountType, EmailAccountType, OAuthAccountType, } from '@proofzero/types/account' import { - IdentityGroupURN, + type IdentityGroupURN, IdentityGroupURNSpace, } from '@proofzero/urns/identity-group' -import { createAnalyticsEvent } from '@proofzero/utils/analytics' -import { type IdentityURN } from '@proofzero/urns/identity' + export type InviteRes = { inviteCode: string } @@ -31,8 +27,6 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( ) as IdentityGroupURN const jwt = await requireJWT(request, context.env) - const parsedJwt = parseJwt(jwt!) - const identityURN = parsedJwt.sub as IdentityURN const fd = await request.formData() const accountType = fd.get('accountType') as @@ -64,18 +58,6 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( identityGroupURN: groupURN, }) - await createAnalyticsEvent({ - eventName: 'member_invited_to_group', - distinctId: identityURN, - apiKey: context.env.POSTHOG_API_KEY, - groups: { - group: groupID, - }, - properties: { - groupID: groupID, - }, - }) - return json({ inviteCode, } as InviteRes) diff --git a/apps/console/app/routes/apps/delete.tsx b/apps/console/app/routes/apps/delete.tsx index 6813de9eb6..d033083b46 100644 --- a/apps/console/app/routes/apps/delete.tsx +++ b/apps/console/app/routes/apps/delete.tsx @@ -2,10 +2,7 @@ import { redirect } from '@remix-run/cloudflare' import type { ActionFunction } from '@remix-run/cloudflare' import createCoreClient from '@proofzero/platform-clients/core' import { requireJWT } from '~/utilities/session.server' -import { - getAuthzHeaderConditionallyFromToken, - parseJwt, -} from '@proofzero/utils' +import { getAuthzHeaderConditionallyFromToken } from '@proofzero/utils' import { generateTraceContextHeaders } from '@proofzero/platform-middleware/trace' import { JsonError, @@ -13,8 +10,6 @@ import { getRollupReqFunctionErrorWrapper, } from '@proofzero/utils/errors' import { BadRequestError, InternalServerError } from '@proofzero/errors' -import { createAnalyticsEvent } from '@proofzero/utils/analytics' -import { type IdentityURN } from '@proofzero/urns/identity' export const action: ActionFunction = getRollupReqFunctionErrorWrapper( async ({ request, context }) => { @@ -25,8 +20,6 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( throw new BadRequestError({ message: 'Client ID is required' }) const jwt = await requireJWT(request, context.env) - const parsedJwt = parseJwt(jwt as string) - const identityURN = parsedJwt.sub as IdentityURN const coreClient = createCoreClient(context.env.Core, { ...getAuthzHeaderConditionallyFromToken(jwt), @@ -34,14 +27,6 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( }) try { await coreClient.starbase.deleteApp.mutate({ clientId }) - await createAnalyticsEvent({ - apiKey: context.env.POSTHOG_API_KEY, - eventName: 'app_deleted', - distinctId: identityURN, - properties: { - client_id: clientId, - }, - }) return redirect('/') } catch (error) { const cause = getErrorCause(error) diff --git a/apps/console/app/routes/apps/new.tsx b/apps/console/app/routes/apps/new.tsx index ab9ebf0eaa..b19d100ee8 100644 --- a/apps/console/app/routes/apps/new.tsx +++ b/apps/console/app/routes/apps/new.tsx @@ -75,13 +75,14 @@ export default function CreateNewApp() {
posthog?.capture('new_app_created')} disabled={isSubmitting} > {isSubmitting && ( diff --git a/apps/passport/app/root.tsx b/apps/passport/app/root.tsx index 9aae45190c..dc66d3afd9 100644 --- a/apps/passport/app/root.tsx +++ b/apps/passport/app/root.tsx @@ -256,9 +256,6 @@ export default function App() { autocapture: false, }) posthog?.reset() - posthog?.group('app', browserEnv?.appProps?.clientId, { - name: browserEnv?.appProps?.name, - }) } catch (ex) { console.error(ex) } diff --git a/apps/passport/app/routes/authorize.tsx b/apps/passport/app/routes/authorize.tsx index 4d1dc6456d..9cbc03df7c 100644 --- a/apps/passport/app/routes/authorize.tsx +++ b/apps/passport/app/routes/authorize.tsx @@ -46,7 +46,6 @@ import { Helmet } from 'react-helmet' import { getRGBColor, getTextColor } from '@proofzero/design-system/src/helpers' import { AccountURNSpace } from '@proofzero/urns/account' import type { DropdownSelectListItem } from '@proofzero/design-system/src/atoms/dropdown/DropdownSelectList' -import { createAnalyticsEvent } from '@proofzero/utils/analytics' export type UserProfile = { displayName: string @@ -374,19 +373,6 @@ export const action: ActionFunction = async ({ request, context }) => { throw json({ message: 'Failed to authorize' }, 400) } - await createAnalyticsEvent({ - eventName: 'app_authorized', - distinctId: identityURN, - apiKey: context.env.POSTHOG_API_KEY, - groups: { - app: clientId, - }, - properties: { - clientId: clientId, - scope: scope, - }, - }) - const redirectParams = new URLSearchParams({ code: authorizeRes.code, state: authorizeRes.state, @@ -444,8 +430,8 @@ export default function Authorize() { return [AuthorizationControlSelection.ALL] } else { return connectedAccounts?.length - ? connectedAccounts.filter( - (acc) => persona.connected_accounts?.includes(acc.value) + ? connectedAccounts.filter((acc) => + persona.connected_accounts?.includes(acc.value) ) : [] } @@ -457,8 +443,8 @@ export default function Authorize() { return [AuthorizationControlSelection.ALL] } else { return connectedSmartContractWallets?.length - ? connectedSmartContractWallets.filter( - (acc) => persona.erc_4337?.includes(acc.value) + ? connectedSmartContractWallets.filter((acc) => + persona.erc_4337?.includes(acc.value) ) : [] } diff --git a/apps/passport/app/routes/settings.tsx b/apps/passport/app/routes/settings.tsx index c83f306cb8..3229187b8f 100644 --- a/apps/passport/app/routes/settings.tsx +++ b/apps/passport/app/routes/settings.tsx @@ -159,7 +159,9 @@ export default function SettingsLayout() { // need to identify only once useEffect(() => { - if (!isIdentified) posthog?.identify(identityURN) + if (!isIdentified) { + posthog?.identify(identityURN) + } setIsIdentified(true) }, [isIdentified]) diff --git a/apps/passport/app/routes/settings/accounts/rename.tsx b/apps/passport/app/routes/settings/accounts/rename.tsx index 980b093851..2586b342ea 100644 --- a/apps/passport/app/routes/settings/accounts/rename.tsx +++ b/apps/passport/app/routes/settings/accounts/rename.tsx @@ -1,21 +1,9 @@ import type { ActionFunction } from '@remix-run/cloudflare' import { getCoreClient } from '~/platform.server' -import { - getDefaultAuthzParams, - getValidatedSessionContext, -} from '~/session.server' import { getRollupReqFunctionErrorWrapper } from '@proofzero/utils/errors' -import { createAnalyticsEvent } from '@proofzero/utils/analytics' export const action: ActionFunction = getRollupReqFunctionErrorWrapper( async ({ request, context }) => { - const { identityURN } = await getValidatedSessionContext( - request, - getDefaultAuthzParams(request), - context.env, - context.traceSpan - ) - const formData = await request.formData() const name = formData.get('name') as string const accountURN = formData.get('id') as string @@ -25,16 +13,6 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( nickname: name, }) - await createAnalyticsEvent({ - apiKey: context.env.POSTHOG_API_KEY, - distinctId: identityURN, - eventName: 'account_renamed', - properties: { - accountId: accountURN, - nickname: name, - }, - }) - return null } ) diff --git a/apps/passport/app/routes/settings/advanced.tsx b/apps/passport/app/routes/settings/advanced.tsx index c2f599f6a6..e48b314dda 100644 --- a/apps/passport/app/routes/settings/advanced.tsx +++ b/apps/passport/app/routes/settings/advanced.tsx @@ -80,6 +80,12 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( await coreClient.identity.deleteIdentityNode.mutate({ identity: identityURN, }) + + await createAnalyticsEvent({ + apiKey: context.env.POSTHOG_API_KEY, + eventName: 'identity_deleted_identity', + distinctId: identityURN, + }) } catch (ex) { console.error(ex) throw new RollupError({ @@ -89,12 +95,6 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( }) } - await createAnalyticsEvent({ - apiKey: context.env.POSTHOG_API_KEY, - eventName: 'delete_rollup_identity', - distinctId: identityURN, - }) - return await destroyUserSession( request, '/', diff --git a/apps/passport/app/routes/settings/applications/$clientId/revoke.tsx b/apps/passport/app/routes/settings/applications/$clientId/revoke.tsx index ffc5ad0da6..15a6bf3855 100644 --- a/apps/passport/app/routes/settings/applications/$clientId/revoke.tsx +++ b/apps/passport/app/routes/settings/applications/$clientId/revoke.tsx @@ -7,13 +7,12 @@ import { getCoreClient } from '~/platform.server' import { getFlashSession, commitFlashSession } from '~/session.server' import { BadRequestError } from '@proofzero/errors' import { getRollupReqFunctionErrorWrapper } from '@proofzero/utils/errors' -import { createAnalyticsEvent } from '@proofzero/utils/analytics' export const action: ActionFunction = getRollupReqFunctionErrorWrapper( async ({ request, params, context }) => { const session = await getFlashSession(request, context.env) - const { jwt, identityURN } = await getValidatedSessionContext( + const { jwt } = await getValidatedSessionContext( request, context.authzQueryParams, context.env, @@ -33,16 +32,6 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( issuer: new URL(request.url).origin, }) - await createAnalyticsEvent({ - apiKey: context.env.POSTHOG_API_KEY, - distinctId: identityURN, - eventName: 'app_authorization_revoked', - properties: { - clientId, - }, - groups: { app: clientId }, - }) - session.flash( 'tooltipMessage', JSON.stringify({ diff --git a/packages/utils/analytics.ts b/packages/utils/analytics.ts index aeb7b9f861..e6750388be 100644 --- a/packages/utils/analytics.ts +++ b/packages/utils/analytics.ts @@ -3,20 +3,17 @@ export const createAnalyticsEvent = async ({ apiKey, distinctId, properties, - groups, }: { eventName: string apiKey: string distinctId: string - groups?: Record properties?: Record }) => { const body = JSON.stringify({ api_key: apiKey, event: eventName, distinct_id: distinctId, - groups: groups, - properties: properties, + properties, }) const init = { diff --git a/platform/account/src/jsonrpc/methods/resolveIdentity.ts b/platform/account/src/jsonrpc/methods/resolveIdentity.ts index c5ac3380fd..bdd9923be6 100644 --- a/platform/account/src/jsonrpc/methods/resolveIdentity.ts +++ b/platform/account/src/jsonrpc/methods/resolveIdentity.ts @@ -38,7 +38,7 @@ export const resolveIdentityMethod = async ({ }): Promise => { const nodeClient = ctx.account - let eventName = 'identity-resolved' + let eventName = 'account_resolved_identity' let resultURN = await nodeClient?.class.getIdentity() if (input.jwt && resultURN) { @@ -56,7 +56,7 @@ export const resolveIdentityMethod = async ({ } else { const name = hexlify(randomBytes(IDENTITY_OPTIONS.length)) urn = IdentityURNSpace.componentizedUrn(name) - eventName = 'identity-created' + eventName = 'account_created_identity' } const caller = router.createCaller(ctx) await caller.account.setIdentity(urn) // this will lazy create an identity node when identity worker is called @@ -73,7 +73,9 @@ export const resolveIdentityMethod = async ({ apiKey: ctx.POSTHOG_API_KEY, eventName, distinctId: resultURN, - groups: { app: input.clientId }, + properties: { + $groups: { app: input.clientId }, + }, }) return { diff --git a/platform/authorization/src/jsonrpc/methods/authorize.ts b/platform/authorization/src/jsonrpc/methods/authorize.ts index b2c4dae438..1ef45c3693 100644 --- a/platform/authorization/src/jsonrpc/methods/authorize.ts +++ b/platform/authorization/src/jsonrpc/methods/authorize.ts @@ -8,6 +8,7 @@ import { initExchangeCodeNodeByName } from '../../nodes' import { hexlify } from '@ethersproject/bytes' import { randomBytes } from '@ethersproject/random' import { PersonaData } from '@proofzero/types/application' +import { createAnalyticsEvent } from '@proofzero/utils/analytics' export const AuthorizeMethodInput = z.object({ identity: IdentityURNInput, @@ -59,5 +60,18 @@ export const authorizeMethod = async ({ personaData ) + // We don't track hacky way to create user session. + if (!scope.includes('admin')) { + await createAnalyticsEvent({ + eventName: 'identity_authorized_app', + distinctId: identity, + apiKey: ctx.POSTHOG_API_KEY, + properties: { + scope: scope, + $groups: { app: clientId }, + }, + }) + } + return { ...result } } diff --git a/platform/authorization/src/jsonrpc/methods/exchangeToken.ts b/platform/authorization/src/jsonrpc/methods/exchangeToken.ts index 5c63aaf515..158956b7c7 100644 --- a/platform/authorization/src/jsonrpc/methods/exchangeToken.ts +++ b/platform/authorization/src/jsonrpc/methods/exchangeToken.ts @@ -38,6 +38,7 @@ import { userClaimsFormatter, } from '@proofzero/security/persona' import { UnauthorizedError } from '@proofzero/errors' +import { createAnalyticsEvent } from '@proofzero/utils/analytics' const AuthenticationCodeInput = z.object({ grantType: z.literal(GrantType.AuthenticationCode), @@ -121,15 +122,30 @@ export const exchangeTokenMethod: ExchangeTokenMethod = async ({ input, }) => { const { grantType } = input + let result, eventObject if (grantType == GrantType.AuthenticationCode) { - return handleAuthenticationCode({ ctx, input }) + result = handleAuthenticationCode({ ctx, input }) + eventObject = 'authn_code' } else if (grantType == GrantType.AuthorizationCode) { - return handleAuthorizationCode({ ctx, input }) + result = handleAuthorizationCode({ ctx, input }) + eventObject = 'auth_code' } else if (grantType == GrantType.RefreshToken) { - return handleRefreshToken({ ctx, input }) + result = handleRefreshToken({ ctx, input }) + eventObject = 'refresh_token' } else { throw new UnsupportedGrantTypeError(grantType) } + + await createAnalyticsEvent({ + eventName: `app_exchanged_${eventObject}`, + distinctId: ctx.identityURN as IdentityURN, + apiKey: ctx.POSTHOG_API_KEY, + properties: { + $groups: { app: input.clientId }, + }, + }) + + return result } const handleAuthenticationCode: ExchangeTokenMethod< diff --git a/platform/authorization/src/jsonrpc/methods/revokeAppAuthorization.ts b/platform/authorization/src/jsonrpc/methods/revokeAppAuthorization.ts index 37264d27e7..9a5db67180 100644 --- a/platform/authorization/src/jsonrpc/methods/revokeAppAuthorization.ts +++ b/platform/authorization/src/jsonrpc/methods/revokeAppAuthorization.ts @@ -5,16 +5,12 @@ import { router } from '@proofzero/platform.core' import { Context } from '../../context' import { initAuthorizationNodeByName } from '../../nodes' -import { - EDGE_AUTHORIZES, - ROLLUP_INTERNAL_ACCESS_TOKEN_URN, -} from '../../constants' +import { EDGE_AUTHORIZES } from '../../constants' import { IdentityURNSpace } from '@proofzero/urns/identity' import { AuthorizationURNSpace } from '@proofzero/urns/authorization' -import { generateJKU, getPrivateJWK } from '../../jwk' -import { generateTraceContextHeaders } from '@proofzero/platform-middleware/trace' import { EDGE_HAS_REFERENCE_TO } from '@proofzero/types/graph' +import { createAnalyticsEvent } from '@proofzero/utils/analytics' export const RevokeAppAuthorizationMethodInput = z.object({ clientId: z.string().min(1), @@ -143,4 +139,13 @@ export const revokeAppAuthorizationMethod: RevokeAppAuthorizationMethod = } await authorizationNode.class.deleteAll() + + await createAnalyticsEvent({ + apiKey: ctx.POSTHOG_API_KEY, + distinctId: identityURN, + eventName: 'identity_revoked_authorization', + properties: { + $groups: { app: clientId }, + }, + }) } diff --git a/platform/identity/src/jsonrpc/methods/identity-groups/createIdentityGroup.ts b/platform/identity/src/jsonrpc/methods/identity-groups/createIdentityGroup.ts index 34843366c4..6dfbe60d20 100644 --- a/platform/identity/src/jsonrpc/methods/identity-groups/createIdentityGroup.ts +++ b/platform/identity/src/jsonrpc/methods/identity-groups/createIdentityGroup.ts @@ -7,7 +7,8 @@ import { IdentityGroupURNSpace } from '@proofzero/urns/identity-group' import { EDGE_MEMBER_OF_IDENTITY_GROUP } from '@proofzero/types/graph' import { Context } from '../../../context' -import { IdentityURN } from '@proofzero/urns/identity' +import type { IdentityURN } from '@proofzero/urns/identity' +import { createAnalyticsEvent } from '@proofzero/utils/analytics' export const CreateIdentityGroupInputSchema = z.object({ name: z.string(), @@ -39,4 +40,29 @@ export const createIdentityGroup = async ({ tag: EDGE_MEMBER_OF_IDENTITY_GROUP, dst: baseGroupURN, }) + + await createAnalyticsEvent({ + eventName: '$groupidentify', + apiKey: ctx.POSTHOG_API_KEY, + distinctId: ctx.identityURN as IdentityURN, + properties: { + $groups: { group: groupURN }, + $group_type: 'group', + $group_key: groupURN, + $group_set: { + name: input.name, + groupURN: groupURN, + date_joined: new Date().toISOString(), + }, + }, + }) + + await createAnalyticsEvent({ + eventName: 'identity_created_group', + apiKey: ctx.POSTHOG_API_KEY, + distinctId: ctx.identityURN as IdentityURN, + properties: { + $groups: { group: groupURN }, + }, + }) } diff --git a/platform/identity/src/jsonrpc/methods/identity-groups/inviteIdentityGroupMember.ts b/platform/identity/src/jsonrpc/methods/identity-groups/inviteIdentityGroupMember.ts index 59faf87512..ba7732c5fe 100644 --- a/platform/identity/src/jsonrpc/methods/identity-groups/inviteIdentityGroupMember.ts +++ b/platform/identity/src/jsonrpc/methods/identity-groups/inviteIdentityGroupMember.ts @@ -13,6 +13,7 @@ import { router } from '@proofzero/platform.core' import { AccountURN, AccountURNSpace } from '@proofzero/urns/account' import generateRandomString from '@proofzero/utils/generateRandomString' import { IdentityURN } from '@proofzero/urns/identity' +import { createAnalyticsEvent } from '@proofzero/utils/analytics' export const InviteIdentityGroupMemberInputSchema = z.object({ identityGroupURN: IdentityGroupURNValidator, @@ -87,6 +88,15 @@ export const inviteIdentityGroupMember = async ({ inviteCode, }) + await createAnalyticsEvent({ + eventName: 'group_invited_member', + distinctId: inviterIdentityURN, + apiKey: ctx.POSTHOG_API_KEY, + properties: { + $groups: { group: identityGroupURN }, + }, + }) + return { inviteCode, } diff --git a/platform/starbase/src/jsonrpc/methods/createApp.ts b/platform/starbase/src/jsonrpc/methods/createApp.ts index 712fde740d..9877caecb0 100644 --- a/platform/starbase/src/jsonrpc/methods/createApp.ts +++ b/platform/starbase/src/jsonrpc/methods/createApp.ts @@ -5,6 +5,8 @@ import * as oauth from '../../OAuth' import { getApplicationNodeByClientId } from '../../nodes/application' import { ApplicationURNSpace } from '@proofzero/urns/application' import { EDGE_APPLICATION } from '../../types' +import { createAnalyticsEvent } from '@proofzero/utils/analytics' +import { ServicePlanType } from '@proofzero/types/identity' export const CreateAppInputSchema = z.object({ clientName: z.string(), @@ -55,6 +57,32 @@ export const createApp = async ({ console.log(`Created app ${clientId} for account ${ctx.accountURN}`) } + await createAnalyticsEvent({ + eventName: '$groupidentify', + apiKey: ctx.POSTHOG_API_KEY, + distinctId: ctx.identityURN, + properties: { + $groups: { app: clientId }, + $group_type: 'app', + $group_key: clientId, + $group_set: { + name: input.clientName, + plan: ServicePlanType.FREE, + clientId: clientId, + date_joined: new Date().toISOString(), + }, + }, + }) + + await createAnalyticsEvent({ + eventName: 'identity_created_app', + apiKey: ctx.POSTHOG_API_KEY, + distinctId: ctx.identityURN, + properties: { + $groups: { app: clientId }, + }, + }) + return { clientId: clientId, } diff --git a/platform/starbase/src/jsonrpc/methods/deleteApp.ts b/platform/starbase/src/jsonrpc/methods/deleteApp.ts index 37cbe9c0f9..bdcb658e78 100644 --- a/platform/starbase/src/jsonrpc/methods/deleteApp.ts +++ b/platform/starbase/src/jsonrpc/methods/deleteApp.ts @@ -7,6 +7,8 @@ import { ApplicationURNSpace } from '@proofzero/urns/application' import { AppClientIdParamSchema } from '../validators/app' import { EDGE_APPLICATION } from '../../types' import { EDGE_HAS_REFERENCE_TO } from '@proofzero/types/graph' +import { createAnalyticsEvent } from '@proofzero/utils/analytics' +import type { IdentityURN } from '@proofzero/urns/identity' export const DeleteAppInput = AppClientIdParamSchema @@ -64,5 +66,12 @@ export const deleteApp = async ({ }) await appDO.class.delete() - console.log(`Deleted app ${input.clientId} from account ${ctx.accountURN}`) + await createAnalyticsEvent({ + apiKey: ctx.POSTHOG_API_KEY, + eventName: 'identity_deleted_app', + distinctId: ctx.identityURN as IdentityURN, + properties: { + $groups: { app: input.clientId }, + }, + }) } diff --git a/platform/starbase/src/jsonrpc/methods/publishApp.ts b/platform/starbase/src/jsonrpc/methods/publishApp.ts index d07d1ae61b..dd3b5cf0ff 100644 --- a/platform/starbase/src/jsonrpc/methods/publishApp.ts +++ b/platform/starbase/src/jsonrpc/methods/publishApp.ts @@ -8,6 +8,7 @@ import { createAnalyticsEvent } from '@proofzero/utils/analytics' import { Context } from '../context' import { getApplicationNodeByClientId } from '../../nodes/application' +import type { IdentityURN } from '@proofzero/urns/identity' export const PublishAppInput = z.object({ clientId: z.string(), @@ -57,25 +58,14 @@ export const publishApp = async ({ await appDO.class.publish(input.published) - let eventName = undefined - - if (!appDetails.published && input.published) { - eventName = 'app_published' - } else if (appDetails.published && !input.published) { - /** - * We can unpublish an app only if it was published before. - */ - eventName = 'app_unpublished' - } - - if (eventName) - await createAnalyticsEvent({ - distinctId: ctx.accountURN as string, - eventName, - apiKey: ctx.POSTHOG_API_KEY, - properties: { client_id: input.clientId }, - groups: { app: input.clientId }, - }) + await createAnalyticsEvent({ + distinctId: ctx.identityURN as IdentityURN, + eventName: input.published + ? 'identity_published_app' + : 'identity_unpublished_app', + apiKey: ctx.POSTHOG_API_KEY, + properties: { $groups: { app: input.clientId } }, + }) return { published: true, diff --git a/platform/starbase/src/jsonrpc/methods/setAppPlan.ts b/platform/starbase/src/jsonrpc/methods/setAppPlan.ts index b731c497dc..c9db49fad5 100644 --- a/platform/starbase/src/jsonrpc/methods/setAppPlan.ts +++ b/platform/starbase/src/jsonrpc/methods/setAppPlan.ts @@ -54,17 +54,6 @@ export const setAppPlan = async ({ dst: appURN, }) } - - await createAnalyticsEvent({ - eventName: 'app_pro_plan_set', - apiKey: ctx.POSTHOG_API_KEY, - distinctId: input.identityURN, - groups: { app: input.clientId }, - properties: { - clientId: input.clientId, - plan, - }, - }) } else { await caller.edges.removeEdge({ src: identityURN, @@ -72,4 +61,28 @@ export const setAppPlan = async ({ dst: appURN, }) } + + // This is the way how we can update group properties + // https://posthog.com/tutorials/frontend-vs-backend-group-analytics + await createAnalyticsEvent({ + eventName: '$groupidentify', + apiKey: ctx.POSTHOG_API_KEY, + distinctId: identityURN, + properties: { + $group_type: 'app', + $group_key: clientId, + $group_set: { + plan, + }, + }, + }) + + await createAnalyticsEvent({ + eventName: `app_set_${plan}_plan`, + apiKey: ctx.POSTHOG_API_KEY, + distinctId: identityURN, + properties: { + $groups: { app: clientId }, + }, + }) }