sdk: update nextjs and web sdk

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-05-31 20:47:36 +02:00
parent 51bb0c969d
commit f75fe498ba
3 changed files with 101 additions and 55 deletions

View File

@@ -126,6 +126,21 @@ const profileId = '123';
setProfileId(profileId); setProfileId(profileId);
``` ```
Or if you want to identify the user with a server component.
```typescript
import { SetProfileId } from '@openpanel/nextjs';
export function Layout({ children }) {
return (
<>
<SetProfileId value={'123'} />
{children}
</>
)
}
```
#### Additional data #### Additional data
This method does the same as `setProfileId` but also allows you to update the profile with additional data. This method does the same as `setProfileId` but also allows you to update the profile with additional data.
@@ -146,6 +161,21 @@ setProfile({
}); });
``` ```
Or if you want to identify the user with a server component.
```typescript
import { SetProfile } from '@openpanel/nextjs';
export function Layout({ children }) {
return (
<>
<SetProfile profileId={'12'} firstName={'Joe'} lastName={'Doe'} email={'joe.doe@openpanel.dev'} avatar={'https://image.com'} properties={{...}} />
{children}
</>
)
}
```
#### Increment property #### Increment property
Increment a property on the profile. Increment a property on the profile.
@@ -184,7 +214,7 @@ import { clear } from '@openpanel/nextjs';
clear(); clear();
``` ```
### Track server events ## Track server events
If you want to track server-side events, you should create an instance of our Javascript SDK. It's exported from `@openpanel/nextjs` If you want to track server-side events, you should create an instance of our Javascript SDK. It's exported from `@openpanel/nextjs`
@@ -209,7 +239,24 @@ opServer.event('my_server_event', { ok: '✅' });
opServer.event('my_server_event', { profileId: '123', ok: '✅' }); opServer.event('my_server_event', { profileId: '123', ok: '✅' });
``` ```
### Proxy events ### Serverless & Vercel
If you log events in a serverless environment like Vercel, you can use `waitUntil` to ensure the event is logged before the function is done.
Otherwise your function might close before the event is logged. Read more about it [here](https://vercel.com/docs/functions/functions-api-reference#waituntil).
```typescript
import { waitUntil } from '@vercel/functions';
import { opServer } from 'path/to/your-sdk-instance';
export function GET() {
// Returns a response immediately while keeping the function alive
waitUntil(opServer.event('my_server_event', { foo: 'bar' }));
return new Response(`You're event has been logged!`);
}
```
## Proxy events
With `createNextRouteHandler` you can proxy your events through your server, this will ensure all events are tracked since there is a lot of adblockers that block requests to third party domains. With `createNextRouteHandler` you can proxy your events through your server, this will ensure all events are tracked since there is a lot of adblockers that block requests to third party domains.

View File

@@ -50,11 +50,11 @@ export function OpenpanelProvider({
cdnUrl, cdnUrl,
...options ...options
}: OpenpanelProviderProps) { }: OpenpanelProviderProps) {
const events: { name: OpenpanelMethods; value: unknown }[] = [ const methods: { name: OpenpanelMethods; value: unknown }[] = [
{ name: 'ctor', value: options }, { name: 'ctor', value: options },
]; ];
if (profileId) { if (profileId) {
events.push({ name: 'setProfileId', value: profileId }); methods.push({ name: 'setProfileId', value: profileId });
} }
return ( return (
<> <>
@@ -62,9 +62,9 @@ export function OpenpanelProvider({
<Script <Script
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `window.op = window.op || function(...args) {(window.op.q = window.op.q || []).push(args)}; __html: `window.op = window.op || function(...args) {(window.op.q = window.op.q || []).push(args)};
${events ${methods
.map((event) => { .map((method) => {
return `window.op('${event.name}', ${JSON.stringify(event.value)});`; return `window.op('${method.name}', ${JSON.stringify(method.value)});`;
}) })
.join('\n')}`, .join('\n')}`,
}} }}
@@ -89,6 +89,20 @@ export function SetProfileId({ value }: SetProfileIdProps) {
); );
} }
type SetProfileProps = UpdateProfilePayload;
export function SetProfile(props: SetProfileProps) {
return (
<>
<Script
dangerouslySetInnerHTML={{
__html: `window.op('setProfile', ${JSON.stringify(props)});`,
}}
/>
</>
);
}
export function trackEvent( export function trackEvent(
name: string, name: string,
data?: PostEventPayload['properties'] data?: PostEventPayload['properties']

View File

@@ -5,7 +5,6 @@ export interface OpenpanelEventOptions {
export interface PostEventPayload { export interface PostEventPayload {
name: string; name: string;
timestamp: string; timestamp: string;
deviceId?: string;
profileId?: string; profileId?: string;
properties?: Record<string, unknown> & OpenpanelEventOptions; properties?: Record<string, unknown> & OpenpanelEventOptions;
} }
@@ -36,13 +35,9 @@ export interface OpenpanelSdkOptions {
clientId: string; clientId: string;
clientSecret?: string; clientSecret?: string;
verbose?: boolean; verbose?: boolean;
setDeviceId?: (deviceId: string) => void;
getDeviceId?: () => string | null | undefined;
removeDeviceId?: () => void;
} }
export interface OpenpanelState { export interface OpenpanelState {
deviceId?: string;
profileId?: string; profileId?: string;
properties: Record<string, unknown>; properties: Record<string, unknown>;
} }
@@ -149,9 +144,9 @@ export class OpenpanelSdk<
this.state.profileId = profileId; this.state.profileId = profileId;
} }
public setProfile(payload: UpdateProfilePayload) { public async setProfile(payload: UpdateProfilePayload) {
this.setProfileId(payload.profileId); this.setProfileId(payload.profileId);
this.api.fetch<UpdateProfilePayload, string>('/profile', { return this.api.fetch<UpdateProfilePayload, string>('/profile', {
...payload, ...payload,
properties: { properties: {
...this.state.properties, ...this.state.properties,
@@ -160,7 +155,7 @@ export class OpenpanelSdk<
}); });
} }
public increment( public async increment(
property: string, property: string,
value: number, value: number,
options?: OpenpanelEventOptions options?: OpenpanelEventOptions
@@ -169,14 +164,17 @@ export class OpenpanelSdk<
if (!profileId) { if (!profileId) {
return console.log('No profile id'); return console.log('No profile id');
} }
this.api.fetch<IncrementProfilePayload, string>('/profile/increment', { return this.api.fetch<IncrementProfilePayload, string>(
'/profile/increment',
{
profileId, profileId,
property, property,
value, value,
}); }
);
} }
public decrement( public async decrement(
property: string, property: string,
value: number, value: number,
options?: OpenpanelEventOptions options?: OpenpanelEventOptions
@@ -185,31 +183,30 @@ export class OpenpanelSdk<
if (!profileId) { if (!profileId) {
return console.log('No profile id'); return console.log('No profile id');
} }
this.api.fetch<DecrementProfilePayload, string>('/profile/decrement', { return this.api.fetch<DecrementProfilePayload, string>(
'/profile/decrement',
{
profileId, profileId,
property, property,
value, value,
}); }
);
} }
public event(name: string, properties?: PostEventPayload['properties']) { public async event(
name: string,
properties?: PostEventPayload['properties']
) {
const profileId = properties?.profileId ?? this.state.profileId; const profileId = properties?.profileId ?? this.state.profileId;
delete properties?.profileId; delete properties?.profileId;
this.api return this.api.fetch<PostEventPayload, string>('/event', {
.fetch<PostEventPayload, string>('/event', {
name, name,
properties: { properties: {
...this.state.properties, ...this.state.properties,
...(properties ?? {}), ...(properties ?? {}),
}, },
timestamp: this.timestamp(), timestamp: this.timestamp(),
deviceId: this.getDeviceId(),
profileId, profileId,
})
.then((deviceId) => {
if (this.options.setDeviceId && deviceId) {
this.options.setDeviceId(deviceId);
}
}); });
} }
@@ -221,11 +218,7 @@ export class OpenpanelSdk<
} }
public clear() { public clear() {
this.state.deviceId = undefined;
this.state.profileId = undefined; this.state.profileId = undefined;
if (this.options.removeDeviceId) {
this.options.removeDeviceId();
}
} }
// Private // Private
@@ -233,12 +226,4 @@ export class OpenpanelSdk<
private timestamp() { private timestamp() {
return new Date().toISOString(); return new Date().toISOString();
} }
private getDeviceId() {
if (this.state.deviceId) {
return this.state.deviceId;
} else if (this.options.getDeviceId) {
this.state.deviceId = this.options.getDeviceId() || undefined;
}
}
} }