identify with track

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-08-12 21:14:39 +02:00
parent 9fcc31319d
commit c34c2cb93b
2 changed files with 81 additions and 23 deletions

View File

@@ -2,13 +2,13 @@ import type { GeoLocation } from '@/utils/parseIp';
import { getClientIp, parseIp } from '@/utils/parseIp'; import { getClientIp, parseIp } from '@/utils/parseIp';
import { parseUserAgent } from '@/utils/parseUserAgent'; import { parseUserAgent } from '@/utils/parseUserAgent';
import type { FastifyReply, FastifyRequest } from 'fastify'; import type { FastifyReply, FastifyRequest } from 'fastify';
import { assocPath, pathOr, pick } from 'ramda'; import { assocPath, path, pathOr, pick } from 'ramda';
import { generateDeviceId } from '@openpanel/common'; import { generateDeviceId } from '@openpanel/common';
import { import {
createProfileAlias, createProfileAlias,
getProfileById, getProfileById,
getProfileId, getProfileIdCached,
getSalts, getSalts,
upsertProfile, upsertProfile,
} from '@openpanel/db'; } from '@openpanel/db';
@@ -42,32 +42,53 @@ export function getStringHeaders(headers: FastifyRequest['headers']) {
); );
} }
function getIdentity(body: TrackHandlerPayload): IdentifyPayload | undefined {
const identity = path<IdentifyPayload>(
['properties', '__identify'],
body.payload
);
return (
identity ||
(body.payload.profileId
? {
profileId: body.payload.profileId,
}
: undefined)
);
}
export async function handler( export async function handler(
request: FastifyRequest<{ request: FastifyRequest<{
Body: TrackHandlerPayload; Body: TrackHandlerPayload;
}>, }>,
reply: FastifyReply reply: FastifyReply
) { ) {
const ip = getClientIp(request)!; const ip =
path<string>(['properties', '__ip'], request.body.payload) ||
getClientIp(request)!;
const ua = request.headers['user-agent']!; const ua = request.headers['user-agent']!;
const projectId = request.client?.projectId; const projectId = request.client?.projectId;
const profileId =
projectId && request.body.payload.profileId
? await getProfileId({
projectId,
profileId: request.body.payload.profileId,
})
: undefined;
if (profileId) {
request.body.payload.profileId = profileId;
}
if (!projectId) { if (!projectId) {
reply.status(400).send('missing origin'); reply.status(400).send('missing origin');
return; return;
} }
const identity = getIdentity(request.body);
const profileId = identity?.profileId
? await getProfileIdCached({
projectId,
profileId: identity?.profileId,
})
: undefined;
// We might get a profileId from the alias table
// If we do, we should use that instead of the one from the payload
if (profileId) {
request.body.payload.profileId = profileId;
}
switch (request.body.type) { switch (request.body.type) {
case 'track': { case 'track': {
const [salts, geo] = await Promise.all([getSalts(), parseIp(ip)]); const [salts, geo] = await Promise.all([getSalts(), parseIp(ip)]);
@@ -87,14 +108,32 @@ export async function handler(
ua, ua,
}) })
: ''; : '';
await track({
payload: request.body.payload, const promises = [
currentDeviceId, track({
previousDeviceId, payload: request.body.payload,
projectId, currentDeviceId,
geo, previousDeviceId,
headers: getStringHeaders(request.headers), projectId,
}); geo,
headers: getStringHeaders(request.headers),
}),
];
// If we have more than one property in the identity object, we should identify the user
// Otherwise its only a profileId and we should not identify the user
if (identity && Object.keys(identity).length > 1) {
promises.push(
identify({
payload: identity,
projectId,
geo,
ua,
})
);
}
await Promise.all(promises);
break; break;
} }
case 'identify': { case 'identify': {

View File

@@ -21,6 +21,25 @@ Sets global properties that will be included with every subsequent event.
Tracks a custom event with the given name and optional properties. Tracks a custom event with the given name and optional properties.
**Tips**
You can identify the user directly with this method.
```js filename="Example shown in JavaScript"
track('your_event_name', {
foo: 'bar',
baz: 'qux',
// reserved property name
__identify: {
profileId: 'your_user_id', // required
email: 'your_user_email',
firstName: 'your_user_name',
lastName: 'your_user_name',
avatar: 'your_user_avatar',
}
});
```
### identify ### identify
Associates the current user with a unique identifier and optional traits. Associates the current user with a unique identifier and optional traits.