update docs

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-08-06 23:04:08 +02:00
committed by Carl-Gerhard Lindesvärd
parent 2226cb463d
commit 03cee826ff
23 changed files with 684 additions and 570 deletions

1
.prettierignore Normal file
View File

@@ -0,0 +1 @@
*.mdx

View File

@@ -64,7 +64,7 @@ const Instructions = ({ framework, client }: Props) => {
<div className="flex flex-col gap-4">
<p>Copy the code below and insert it to you website</p>
<Syntax
code={`<script src="https://openpanel.dev/op.js" defer async></script>
code={`<script src="https://openpanel.dev/op1.js" defer async></script>
<script>
window.op = window.op || function (...args) { (window.op.q = window.op.q || []).push(args); };
window.op('ctor', {
@@ -252,13 +252,13 @@ app.listen(3000, () => {
<strong>Create a instance</strong>
<p>
Create a new instance of OpenpanelSdk. You can use this SDK in any JS
Create a new instance of OpenPanel. You can use this SDK in any JS
environment. You should omit clientSecret if you use this on web!
</p>
<Syntax
code={`import { OpenpanelSdk } from '@openpanel/sdk';
code={`import { OpenPanel } from '@openpanel/sdk';
const op = new OpenpanelSdk({
const op = new OpenPanel({
clientId: '${clientId}',
// mostly for backend and apps that can't rely on CORS
clientSecret: '${clientSecret}',

View File

@@ -43,4 +43,4 @@
]
},
"prettier": "@openpanel/prettier-config"
}
}

View File

@@ -0,0 +1,8 @@
##### Common options
- `apiUrl` - The url of the openpanel API or your self-hosted instance
- `clientId` - The client id of your application
- `clientSecret` - The client secret of your application (**only required for server-side events**)
- `filter` - A function that will be called before sending an event. If it returns false, the event will not be sent
- `disabled` - If true, the library will not send any events
- `waitForProfile` - If true, the library will wait for the profile to be set before sending events

View File

@@ -1,5 +1,6 @@
- `url` - The url of the openpanel API or your self-hosted instance
- `clientId` - The client id of your application
##### Web options
- `trackScreenViews` - If true, the library will automatically track screen views
- `trackOutgoingLinks` - If true, the library will automatically track outgoing links
- `trackAttributes` - If true, the library will automatically track attributes

View File

@@ -12,7 +12,7 @@ export default function App({ Component, pageProps }: AppProps) {
</Head>
<Component {...pageProps} />
<Script
src="https://openpanel.dev/op.js"
src="https://openpanel.dev/op1.js"
async
defer
strategy="afterInteractive"

View File

@@ -4,21 +4,22 @@
"type": "separator",
"title": "Frameworks"
},
"script": "Script",
"script": "Web (Script Tag)",
"web": "Web (Module)",
"nextjs": "Next.js",
"react": "React",
"react-native": "React-Native",
"remix": "Remix",
"vue": "Vue",
"astro": "Astro",
"node": "Node (backend)",
"node": "Node",
"express": "Express (backend)",
"-- Others": {
"type": "separator",
"title": "Others"
},
"javascript": "Javascript SDK",
"web": "Web SDK",
"javascript": "JavaScript",
"api": "API",
"export": "Export"
}
"export": "Export",
"migration": "Migrations"
}

View File

@@ -1,32 +1,144 @@
import Link from 'next/link';
import { Steps, Tabs } from 'nextra/components';
# OpenPanel REST API with cURL
# API
This guide demonstrates how to interact with the OpenPanel API using cURL. These examples provide a low-level understanding of the API endpoints and can be useful for testing or for integrations where a full SDK isn't available.
We'll add more SDKs in the future but you can always use our REST API to send events.
## Good to know
- If you want to track **geo location** you'll need to pass the `ip` property as a header `x-client-ip`
- If you want to track **device information** you'll need to pass the `user-agent` property as a header `user-agent`
## Authentication
To authenticate with the API, you need to use your `clientId` and `clientSecret` (you can find your clients under Settings -> Clients, create a new client if you don't have one with a `clientSecret`).
We expect you to send `openpanel-client-id` and `openpanel-client-secret` headers with your requests.
### Example
This request will create an event with the name `my_event` and the property `foo` set to `bar` and the timestamp set to `2024-03-28T08:42:54.319Z`.
All requests to the OpenPanel API require authentication. You'll need to include your `clientId` and `clientSecret` in the headers of each request.
```bash
curl 'https://api.openpanel.dev/event' \
-H 'content-type: application/json' \
-H 'openpanel-client-id: CLIENT_ID' \
-H 'openpanel-client-secret: CLIENT_SECRET' \
--data-raw '{"name":"my_event","properties":{"foo":"bar"},"timestamp":"2024-03-28T08:42:54.319Z"}'
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET"
```
### Payload
## Usage
The payload should be a JSON object with the following fields:
### Base URL
- `name` (string): The name of the event.
- `properties` (object): The properties of the event.
- `timestamp` (string): The timestamp of the event in ISO 8601 format.
All API requests should be made to:
```
https://api.openpanel.dev
```
### Tracking Events
To track an event:
```bash
curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
"type": "track",
"payload": {
"name": "my_event",
"properties": {
"foo": "bar"
}
}
}'
```
### Identifying Users
To identify a user:
```bash
curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
"type": "identify",
"payload": {
"profileId": "123",
"firstName": "Joe",
"lastName": "Doe",
"email": "joe@doe.com",
"properties": {
"tier": "premium"
}
}
}'
```
### Creating Aliases
To create an alias for a user:
```bash
curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
"type": "alias",
"payload": {
"profileId": "1",
"alias": "a1"
}
}'
```
### Incrementing Properties
To increment a numeric property:
```bash
curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
"type": "increment",
"payload": {
"profileId": "1",
"property": "visits",
"value": 1
}
}'
```
### Decrementing Properties
To decrement a numeric property:
```bash
curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
"type": "decrement",
"payload": {
"profileId": "1",
"property": "visits",
"value": 1
}
}'
```
### Error Handling
The API uses standard HTTP response codes to indicate the success or failure of requests. In case of an error, the response body will contain more information about the error.
Example error response:
```json
{
"error": "Invalid client credentials",
"status": 401
}
```
### Rate Limiting
The API implements rate limiting to prevent abuse. If you exceed the rate limit, you'll receive a 429 (Too Many Requests) response. The response will include headers indicating your rate limit status.
Best Practices
1. Always use HTTPS to ensure secure communication.
2. Store your clientId and clientSecret securely and never expose them in client-side code.
3. Implement proper error handling in your applications.
4. Respect rate limits and implement exponential backoff for retries.

View File

@@ -3,7 +3,7 @@ import { Callout, Steps, Tabs } from 'nextra/components';
import { DeviceIdWarning } from 'src/components/device-id-warning';
import { PersonalDataWarning } from 'src/components/personal-data-warning';
import SdkConfig from 'src/components/sdk-config.mdx';
import CommonSdkConfig from 'src/components/common-sdk-config.mdx';
# Express
@@ -43,7 +43,7 @@ app.use(
app.get('/sign-up', (req, res) => {
// track sign up events
req.op.event('sign-up', {
req.op.track('sign-up', {
email: req.body.email,
});
res.send('Hello World');
@@ -54,10 +54,12 @@ app.listen(3000, () => {
});
```
### Config
### Options
<CommonSdkConfig />
#### Express options
- `clientId` - Your OpenPanel client ID.
- `clientSecret` - Your OpenPanel client secret.
- `trackRequest` - A function that returns `true` if the request should be tracked.
- `getProfileId` - A function that returns the profile ID of the user making the request.
@@ -66,12 +68,12 @@ app.listen(3000, () => {
If `req.op` is not typed you can extend the `Request` interface.
```ts
import { OpenpanelSdk } from '@openpanel/express';
import { OpenPanel } from '@openpanel/express';
declare global {
namespace Express {
export interface Request {
op: OpenpanelSdk;
op: OpenPanel;
}
}
}

View File

@@ -1,9 +1,47 @@
import { Card, Cards } from 'nextra/components';
import { Callout, Card, Cards } from 'nextra/components';
import { BrandLogo } from 'src/components/brand-logo';
# Get started
# Documentation
Create an account on [Openpanel](https://openpanel.dev) and setup your first project (takes 2 minutes). You will get a `clientId` that you will use to initialize Openpanel in your app.
The OpenPanel SDKs provide a set of core methods that allow you to track events, identify users, and more. Here's an overview of the key methods available in the SDKs.
<Callout>
While all OpenPanel SDKs share a common set of core methods, some may have
syntax variations or additional methods specific to their environment. This
documentation provides an overview of the base methods and available SDKs.
</Callout>
## Core Methods
### setGlobalProperties
Sets global properties that will be included with every subsequent event.
### track
Tracks a custom event with the given name and optional properties.
### identify
Associates the current user with a unique identifier and optional traits.
### alias
Creates an alias for a user identifier.
### increment
Increments a numeric property for a user.
### decrement
Decrements a numeric property for a user.
### clear
Clears the current user identifier and ends the session.
## Official SDKs
<Cards>
<Card
@@ -79,3 +117,7 @@ Create an account on [Openpanel](https://openpanel.dev) and setup your first pro
{' '}
</Card>
</Cards>
## Unofficial SDKs
While not officially supported, the following community-contributed SDKs are available.

View File

@@ -1,138 +1,141 @@
import Link from 'next/link';
import { Callout, Steps, Tabs } from 'nextra/components';
import { DeviceIdWarning } from 'src/components/device-id-warning';
import { Callout, Tabs, Steps } from 'nextra/components';
import { PersonalDataWarning } from 'src/components/personal-data-warning';
import SdkConfig from 'src/components/sdk-config.mdx';
import CommonSdkConfig from 'src/components/common-sdk-config.mdx';
import WebSdkConfig from 'src/components/web-sdk-config.mdx';
# Javascript SDK
This is the base SDK for Openpanel. All other SDKs/frameworks are built on top of this one.
The OpenPanel Web SDK allows you to track user behavior on your website using a simple script tag. This guide provides instructions for installing and using the Web SDK in your project.
## Installation
<Steps>
### Install dependencies
### Step 1: Install
```bash
pnpm install @openpanel/sdk
npm install @openpanel/sdk
```
### Initialize
### Step 2: Initialize
```tsx
import { OpenpanelSdk } from '@openpanel/sdk';
```js filename="op.ts"
import { OpenPanel } from '@openpanel/sdk';
const op = new OpenpanelSdk({
clientId: '{YOUR_CLIENT_ID}',
// mostly for backend and apps that can't rely on CORS
clientSecret: '{YOUR_CLIENT_SECRET}',
const op = new OpenPanel({
clientId: 'YOUR_CLIENT_ID',
trackScreenViews: true,
trackOutgoingLinks: true,
trackAttributes: true,
});
```
#### Config
#### Options
- `url` - The url of the openpanel API or your self-hosted instance
- `clientId` - The client id of your application
- `clientSecret` - The client secret of your application (mostly for backend and apps that can't rely on CORS)
<CommonSdkConfig />
### Ready!
### Step 3: Usage
You're now ready to use the library.
```js filename="main.ts"
import { op } from './op.js';
```typescript
// Sends an event with payload foo: bar
op.event('my_event', { foo: 'bar' });
// Identify with profile id
op.setProfileId('123');
// or with additional data
op.setProfile({
profileId: '123',
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@openpanel.dev',
});
// Increment a property
op.increment('app_opened'); // increment by 1
op.increment('app_opened', 5); // increment by 5
// Decrement a property
op.decrement('app_opened'); // decrement by 1
op.decrement('app_opened', 5); // decrement by 5
op.track('my_event', { foo: 'bar' });
```
</Steps>
## Usage
### Track event
### Tracking Events
```typescript
op.event('my_event', { foo: 'bar' });
You can track events with two different methods: by calling the `op.track( directly or by adding `data-track` attributes to your HTML elements.
```ts filename="index.ts"
import { op } from './op.ts';
op.track('my_event', { foo: 'bar' });
```
### Identify
### Identifying Users
#### Set Profile Id
To identify a user, call the `op.identify( method with a unique identifier.
Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior.
```js filename="index.js"
import { op } from './op.ts';
<PersonalDataWarning />
```typescript
const profileId = '123';
op.setProfileId(profileId);
```
#### Additional data
This method does the same as `setProfileId` but also allows you to update the profile with additional data.
<PersonalDataWarning />
```typescript
const profileId = '123';
op.setProfile({
profileId,
// firstName?: string;
// lastName?: string;
// email?: string;
// avatar?: string;
// properties?: Record<string, unknown>;
op.identify({
profileId: '123', // Required
firstName: 'Joe',
lastName: 'Doe',
email: 'joe@doe.com',
properties: {
tier: 'premium',
},
});
```
#### Increment property
### Setting Global Properties
Increment a property on the profile.
To set properties that will be sent with every event:
```typescript
// Increment by 1
op.increment('app_opened');
```js filename="index.js"
import { op } from './op.ts'
// Increment by 5
op.increment('app_opened', 5);
op.setGlobalProperties({
app_version: '1.0.2',
environment: 'production',
});
```
#### Decrement property
### Creating Aliases
Decrement a property on the profile.
To create an alias for a user:
```typescript
// Increment by 1
op.decrement('app_opened');
```js filename="index.js"
import { op } from './op.ts'
// Increment by 5
op.decrement('app_opened', 5);
op.alias({
alias: 'a1',
profileId: '1'
});
```
#### Clear / Logout
### Incrementing Properties
Clear the profile id and all the data.
To increment a numeric property on a user profile.
```typescript
op.clear();
- `value` is the amount to increment the property by. If not provided, the property will be incremented by 1.
```js filename="index.js"
import { op } from './op.ts'
op.increment({
profileId: '1',
property: 'visits',
value: 1 // optional
});
```
### Decrementing Properties
To decrement a numeric property on a user profile.
- `value` is the amount to decrement the property by. If not provided, the property will be decremented by 1.
```js filename="index.js"
import { op } from './op.ts'
op.decrement({
profileId: '1',
property: 'visits',
value: 1 // optional
});
```
### Clearing User Data
To clear the current user's data:
```js filename="index.js"
import { op } from './op.ts'
op.clear()
```

View File

@@ -0,0 +1,3 @@
{
"beta-v1": "Beta to v1"
}

View File

@@ -0,0 +1,38 @@
# Migrate from `beta` to `v1`
We are happy to announce the release of `v1` of the Openpanel SDK. This release includes a lot of improvements and changes to the SDK. This guide will help you migrate from the `beta` version to the `v1` version.
## General
The `Openpanel` class is now called `OpenPanel`!
## Options
- Renamed: `api` to `apiUrl`
- Added: `disabled`
- Added: `filter`
## Methods
- Renamed: `event` method is now called `track`
- Renamed: `setProfile` and `setProfileId` is now called `identify` (and combined)
- Changed: `increment('app_opened', 5)` is now `increment({ name: 'app_opened', value: 5, profileId: '123' })`. So profile ID is now required.
- Changed: `decrement('app_opened', 5)` is now `decrement({ name: 'app_opened', value: 5, profileId: '123' })`. So profile ID is now required.
- Improved: `screenView` method has 2 arguments now. This change is more aligned with `@openpanel/react-native`.
```ts
screenView(properties?: TrackProperties): void;
screenView(path: string, properties?: TrackProperties): void;
// Example
op.screenView('/home', { title: 'Home' }); // path will be "/home"
op.screenView({ title: 'Home' }); // path will be what ever window.location.pathname is
```
## Script tag
- New: `https://openpanel.dev/op1.js` should be used instead of `op.js` (note the filename)
## @openpanel/nextjs
- Renamed: `OpenpanelProvider` to `OpenPanelComponent`
- Removed: All exported methods (trackEvent etc). Use the `useOpenPanel` hook instead since these are client tracking only
- Moved: `createNextRouteHandler` is moved to `@openpanel/nextjs/server`

View File

@@ -3,7 +3,8 @@ import { Callout, Steps, Tabs } from 'nextra/components';
import { DeviceIdWarning } from 'src/components/device-id-warning';
import { PersonalDataWarning } from 'src/components/personal-data-warning';
import SdkConfig from 'src/components/sdk-config.mdx';
import CommonSdkConfig from 'src/components/common-sdk-config.mdx';
import WebSdkConfig from 'src/components/web-sdk-config.mdx';
# Next.js
@@ -22,16 +23,15 @@ pnpm install @openpanel/nextjs
### Initialize
Add `OpenpanelProvider` to your root layout component.
Add `OpenpanelComponent` to your root layout component.
```tsx
import { OpenpanelProvider } from '@openpanel/nextjs';
import { OpenpanelComponent } from '@openpanel/nextjs';
export default RootLayout({ children }) {
return (
<>
<OpenpanelProvider
url="https://api.openpanel.dev"
<OpenpanelComponent
clientId="your-client-id"
trackScreenViews={true}
// trackAttributes={true}
@@ -45,176 +45,197 @@ export default RootLayout({ children }) {
}
```
#### Config
#### Options
<SdkConfig />
<CommonSdkConfig />
<WebSdkConfig />
### Ready!
##### NextJS options
You're now ready to use the library.
- `profileId` - If you have a user id, you can pass it here to identify the user
- `cdnUrl` - The url to the OpenPanel SDK (default: `https://openpanel.dev/op1.js`)
- `filter` - This is a function that will be called before tracking an event. If it returns false the event will not be tracked. [Read more](#filter)
```typescript
import {
decrement,
increment,
setProfile,
setProfileId,
trackEvent,
} from '@openpanel/nextjs';
##### `filter`
// Sends an event with payload foo: bar
trackEvent('my_event', { foo: 'bar' });
This options needs to be a stringified function and cannot access any variables outside of the function.
// Identify with profile id
setProfileId('123');
```tsx
<OpenpanelComponent
clientId="your-client-id"
filter={`
function filter(event) {
return event.name !== 'my_event';
}
`}
/>
```
// or with additional data
setProfile({
profileId: '123',
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@openpanel.dev',
});
To take advantage of typescript you can do the following. _Note `toString`_
```tsx /.toString();/
import { type OpenPanelOptions } from '@openpanel/nextjs';
// Increment a property
increment('app_opened'); // increment by 1
increment('app_opened', 5); // increment by 5
const opFilter = ((event: TrackHandlerPayload) => {
return event.type === 'track' && event.payload.name === 'my_event';
}).toString();
// Decrement a property
decrement('app_opened'); // decrement by 1
decrement('app_opened', 5); // decrement by 5
<OpenpanelComponent
clientId="your-client-id"
filter={opFilter}
/>
```
</Steps>
## Usage
### Track event
### Client components
<Tabs items={['JS', 'window', 'HTML']}>
<Tabs.Tab>
```typescript
import { trackEvent } from '@openpanel/nextjs';
trackEvent('my_event', { foo: 'bar' });
```
</Tabs.Tab>
<Tabs.Tab>
```javascript
window.op('event', 'my_event', { foo: 'bar' });
```
</Tabs.Tab>
<Tabs.Tab>
For this to work you need to enable `trackAttributes` in the config.
```html
<button data-event="my_event" data-foo="bar">Track event</button>
```
</Tabs.Tab>
</Tabs>
For client components you can just use the `useOpenPanel` hook.
### Identify
```tsx
import { useOpenPanel } from '@openpanel/nextjs';
#### Set Profile Id
function YourComponent() {
const op = useOpenPanel();
Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior.
<PersonalDataWarning />
```typescript
import { setProfileId } from '@openpanel/nextjs';
const profileId = '123';
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}
</>
)
return <button onClick={() => op.track('my_event', { foo: 'bar' })}>Trigger event</button>
}
```
#### Additional data
### Server components
This method does the same as `setProfileId` but also allows you to update the profile with additional data.
Since you can't use hooks in server components, you need to create an instance of the SDK. This is exported from `@openpanel/nextjs`.
<PersonalDataWarning />
<Callout>Remember, your client secret is exposed here so do not use this on client side.</Callout>
```typescript
import { setProfile } from '@openpanel/nextjs';
```tsx filename="utils/op.ts"
import { Openpanel } from '@openpanel/nextjs';
const profileId = '123';
setProfile({
profileId,
// firstName?: string;
// lastName?: string;
// email?: string;
// avatar?: string;
// properties?: Record<string, unknown>;
export const op = new Openpanel({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
});
// Now you can use `op` to track events
op.track('my_event', { foo: 'bar' });
```
Refer to the [Javascript SDK](/docs/javascript#usage) for usage instructions.
### Tracking Events
You can track events with two different methods: by calling the `op.track( directly or by adding `data-track` attributes to your HTML elements.
```ts filename="index.ts"
useOpenPanel().track('my_event', { foo: 'bar' });
```
### Identifying Users
To identify a user, call the `op.identify( method with a unique identifier.
```js filename="index.js"
useOpenPanel().identify({
profileId: '123', // Required
firstName: 'Joe',
lastName: 'Doe',
email: 'joe@doe.com',
properties: {
tier: 'premium',
},
});
```
Or if you want to identify the user with a server component.
#### For server components
```typescript
import { SetProfile } from '@openpanel/nextjs';
For server components you can use the `IdentifyComponent` component which is exported from `@openpanel/nextjs`.
> This component is great if you have the user data available on the server side.
```tsx filename="app/nested/layout.tsx"
import { IdentifyComponent } from '@openpanel/nextjs';
export default function Layout({ children }) {
const user = await getCurrentUser()
export function Layout({ children }) {
return (
<>
<SetProfile profileId={'12'} firstName={'Joe'} lastName={'Doe'} email={'joe.doe@openpanel.dev'} avatar={'https://image.com'} properties={{...}} />
<IdentifyComponent
profileId={user.id}
firstName={user.firstName}
lastName={user.lastName}
email={user.email}
properties={{
tier: 'premium',
}}
/>
{children}
</>
)
}
```
#### Increment property
Increment a property on the profile.
### Setting Global Properties
```typescript
import { increment } from '@openpanel/nextjs';
To set properties that will be sent with every event:
// Increment by 1
increment('app_opened');
// Increment by 5
increment('app_opened', 5);
```js filename="index.js"
useOpenPanel().setGlobalProperties({
app_version: '1.0.2',
environment: 'production',
});
```
#### Decrement property
### Creating Aliases
Decrement a property on the profile.
To create an alias for a user:
```typescript
import { decrement } from '@openpanel/nextjs';
// Increment by 1
decrement('app_opened');
// Increment by 5
decrement('app_opened', 5);
```js filename="index.js"
useOpenPanel().alias({
alias: 'a1',
profileId: '1'
});
```
#### Clear / Logout
### Incrementing Properties
Clear the profile id and all the data.
To increment a numeric property on a user profile.
```typescript
import { clear } from '@openpanel/nextjs';
- `value` is the amount to increment the property by. If not provided, the property will be incremented by 1.
clear();
```js filename="index.js"
useOpenPanel().increment({
profileId: '1',
property: 'visits',
value: 1 // optional
});
```
## Track server events
### Decrementing Properties
To decrement a numeric property on a user profile.
- `value` is the amount to decrement the property by. If not provided, the property will be decremented by 1.
```js filename="index.js"
useOpenPanel().decrement({
profileId: '1',
property: 'visits',
value: 1 // optional
});
```
### Clearing User Data
To clear the current user's data:
```js filename="index.js"
useOpenPanel().clear()
```
## Server side
If you want to track server-side events, you should create an instance of our Javascript SDK. It's exported from `@openpanel/nextjs`
@@ -256,25 +277,21 @@ export function GET() {
}
```
## Proxy events
### 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.
```typescript
// file: /app/api/op/[...op]/route.ts
import { createNextRouteHandler } from '@openpanel/nextjs';
```typescript filename="/app/api/op/route.ts"
import { createNextRouteHandler } from '@openpanel/nextjs/server';
export const { POST } = createNextRouteHandler({
clientId: '{YOUR_CLIENT_ID}',
clientSecret: '{YOUR_CLIENT_SECRET}',
});
export const POST = createNextRouteHandler();
```
Remember to change the `url` in the `OpenpanelProvider` to your own server.
Remember to change the `apiUrl` in the `OpenpanelComponent` to your own server.
```tsx
<OpenpanelProvider
url="/api/op" // <---
```tsx {2}
<OpenpanelComponent
apiUrl="/api/op"
clientId="your-client-id"
trackScreenViews={true}
/>

View File

@@ -3,7 +3,7 @@ import { Callout, Steps, Tabs } from 'nextra/components';
import { DeviceIdWarning } from 'src/components/device-id-warning';
import { PersonalDataWarning } from 'src/components/personal-data-warning';
import SdkConfig from 'src/components/sdk-config.mdx';
import CommonSdkConfig from 'src/components/common-sdk-config.mdx';
# React-Native
@@ -15,8 +15,8 @@ import SdkConfig from 'src/components/sdk-config.mdx';
We're dependent on `expo-application` for `buildNumber`, `versionNumber` (and `referrer` on android) and `expo-constants` to get the `user-agent`.
```bash
pnpm install @openpanel/react-native
npx expo install --pnpm expo-application expo-constants
npm install @openpanel/react-native
npx expo install expo-application expo-constants
```
### Initialize
@@ -30,40 +30,9 @@ const op = new Openpanel({
});
```
#### Config
- `url` - The url of the openpanel API or your self-hosted instance
- `clientId` - The client id of your application
- `clientSecret` - The client secret of your application
### Ready!
You're now ready to use the library.
```typescript
// Sends an event with payload foo: bar
op.event('my_event', { foo: 'bar' });
// Identify with profile id
op.setProfileId('123');
// or with additional data
op.setProfile({
profileId: '123',
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@openpanel.dev',
});
// Increment a property
op.increment('app_opened'); // increment by 1
op.increment('app_opened', 5); // increment by 5
// Decrement a property
op.decrement('app_opened'); // decrement by 1
op.decrement('app_opened', 5); // decrement by 5
```
#### Options
<CommonSdkConfig />
</Steps>
## Usage
@@ -71,7 +40,7 @@ op.decrement('app_opened', 5); // decrement by 5
### Track event
```typescript
op.event('my_event', { foo: 'bar' });
op.track('my_event', { foo: 'bar' });
```
### Navigation / Screen views
@@ -139,65 +108,4 @@ op.event('my_event', { foo: 'bar' });
</Tabs.Tab>
</Tabs>
### Identify
#### Set Profile Id
Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior.
<PersonalDataWarning />
```typescript
const profileId = '123';
op.setProfileId(profileId);
```
#### Additional data
This method does the same as `setProfileId` but also allows you to update the profile with additional data.
<PersonalDataWarning />
```typescript
const profileId = '123';
op.setProfile({
profileId,
// firstName?: string;
// lastName?: string;
// email?: string;
// avatar?: string;
// properties?: Record<string, unknown>;
});
```
#### Increment property
Increment a property on the profile.
```typescript
// Increment by 1
op.increment('app_opened');
// Increment by 5
op.increment('app_opened', 5);
```
#### Decrement property
Decrement a property on the profile.
```typescript
// Increment by 1
op.decrement('app_opened');
// Increment by 5
op.decrement('app_opened', 5);
```
#### Clear / Logout
Clear the profile id and all the data.
```typescript
op.clear();
```
For more information on how to use the SDK, check out the [Javascript SDK](/docs/javascript#usage).

View File

@@ -1,129 +1,183 @@
import { Callout, Tabs } from 'nextra/components';
import { Callout, Tabs, Steps } from 'nextra/components';
import { PersonalDataWarning } from 'src/components/personal-data-warning';
import CommonSdkConfig from 'src/components/common-sdk-config.mdx';
import WebSdkConfig from 'src/components/web-sdk-config.mdx';
import SdkConfig from 'src/components/sdk-config.mdx';
# Web (Script Tag)
# Script tag
The OpenPanel Web SDK allows you to track user behavior on your website using a simple script tag. This guide provides instructions for installing and using the Web SDK in your project.
## Installation
Just insert this snippet and replace `YOUR_CLIENT_ID` with your client id.
```html
<script src="https://openpanel.dev/op.js" defer async></script>
```html filename="index.html" /clientId: 'YOUR_CLIENT_ID'/
<script>
window.op =
window.op ||
function (...args) {
(window.op.q = window.op.q || []).push(args);
};
window.op('ctor', {
window.op = window.op||function(...args){(window.op.q=window.op.q||[]).push(args);};
window.op('init', {
clientId: 'YOUR_CLIENT_ID',
trackScreenViews: true,
trackOutgoingLinks: true,
trackAttributes: true,
});
</script>
<script src="https://openpanel.dev/op1.js" defer async></script>
```
### Config
#### Options
<SdkConfig />
<CommonSdkConfig />
<WebSdkConfig />
## Usage
You can let the library track screen views, outgoing links and attributes tracking by setting the `trackScreenViews`, `trackOutgoingLinks` and `trackAttributes` options to `true`.
### Tracking Events
### Track event
You can track events with two different methods: by calling the `window.op('track')` directly or by adding `data-track` attributes to your HTML elements.
<Tabs items={['JS', 'HTML']}>
<Tabs.Tab>
```javascript
window.op('event', 'my_event', { foo: 'bar' });
```
</Tabs.Tab>
<Tabs.Tab>
For this to work you need to enable `trackAttributes` in the config.
```html
<button data-event="my_event" data-foo="bar">Track event</button>
```
</Tabs.Tab>
</Tabs>
### Identify
#### Set Profile Id
Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior.
<PersonalDataWarning />
```javascript
const profileId = '123';
window.op('setProfileId', profileId);
```html filename="index.html"
<button onclick="window.op('track', 'my_event', { foo: 'bar' })">
Track event
</button>
```
#### Additional data
```html filename="index.html"
<button data-track="my_event" data-foo="bar">Track event</button>
```
This method does the same as `setProfileId` but also allows you to update the profile with additional data.
### Identifying Users
<PersonalDataWarning />
To identify a user, call the `window.op('identify')` method with a unique identifier.
```javascript
const profileId = '123';
window.op('setProfile', {
profileId,
// firstName?: string;
// lastName?: string;
// email?: string;
// avatar?: string;
// properties?: Record<string, unknown>;
```js filename="main.js"
window.op('identify', {
profileId: '123', // Required
firstName: 'Joe',
lastName: 'Doe',
email: 'joe@doe.com',
properties: {
tier: 'premium',
},
});
```
#### Increment property
### Setting Global Properties
Increment a property on the profile.
To set properties that will be sent with every event:
```javascript
// Increment by 1
window.op('increment', 'app_opened');
// Increment by 5
window.op('increment', 'app_opened', 5);
```js filename="main.js"
window.op('setGlobalProperties', {
app_version: '1.0.2',
environment: 'production',
});
```
#### Decrement property
### Creating Aliases
Decrement a property on the profile.
To create an alias for a user:
```javascript
// Increment by 1
window.op('decrement', 'app_opened');
// Increment by 5
window.op('decrement', 'app_opened', 5);
```js filename="main.js"
window.op('alias', {
alias: 'a1',
profileId: '1'
});
```
#### Clear / Logout
### Incrementing Properties
Clear the profile id and all the data.
To increment a numeric property on a user profile.
```typescript
- `value` is the amount to increment the property by. If not provided, the property will be incremented by 1.
```js filename="main.js"
window.op('increment', {
profileId: '1',
property: 'visits',
value: 1 // optional
});
```
### Decrementing Properties
To decrement a numeric property on a user profile.
- `value` is the amount to decrement the property by. If not provided, the property will be decremented by 1.
```js filename="main.js"
window.op('decrement', {
profileId: '1',
property: 'visits',
value: 1 // optional
});
```
### Clearing User Data
To clear the current user's data:
```js filename="main.js"
window.op('clear');
```
## Advanced Usage
### Using the Web SDK with NPM
<Steps>
#### Step 1: Install the SDK
```bash
npm install @openpanel/web
```
#### Step 2: Initialize the SDK
```js filename="op.js"
import { OpenPanel } from '@openpanel/web';
const op = new OpenPanel({
clientId: 'YOUR_CLIENT_ID',
trackScreenViews: true,
trackOutgoingLinks: true,
trackAttributes: true,
});
```
#### Step 3: Use the SDK
```js filename="main.js"
import { op } from './op.js';
op.track('my_event', { foo: 'bar' });
```
</Steps>
### Typescript
Is your IDE mad at you for not using typescript? We got you covered.
Getting ts errors when using the SDK? You can add a custom type definition file to your project.
Add this and it will stop complain about `window.op` not being defined.
#### Simple
```typescript
Just paste this code in any of your `.d.ts` files.
```ts filename="op.d.ts"
declare global {
interface Window {
op: {
q?: [string, ...any[]];
(method: string, ...args: any[]): void;
q?: string[][];
(...args: [
'init' | 'track' | 'identify' | 'setGlobalProperties' | 'alias' | 'increment' | 'decrement' | 'clear',
...any[]
]): void;
};
}
}
```
#### Strict typing (from sdk)
Create a `op.d.ts`file and paste the following code:
```ts filename="op.d.ts"
/// <reference types="@openpanel/web" />
```

View File

@@ -1,137 +1,48 @@
import Link from 'next/link';
import { Callout, Steps, Tabs } from 'nextra/components';
import { DeviceIdWarning } from 'src/components/device-id-warning';
import { Callout, Tabs, Steps } from 'nextra/components';
import { PersonalDataWarning } from 'src/components/personal-data-warning';
import SdkConfig from 'src/components/sdk-config.mdx';
import CommonSdkConfig from 'src/components/common-sdk-config.mdx';
import WebSdkConfig from 'src/components/web-sdk-config.mdx';
# Web SDK
This is a wrapper of <Link href="/docs/javascript">Javascript SDK</Link>. It's a simple way to use the Openpanel SDK in your web application.
The OpenPanel Web SDK allows you to track user behavior on your website using a simple script tag. This guide provides instructions for installing and using the Web SDK in your project.
## Installation
<Steps>
### Install dependencies
### Step 1: Install
```bash
pnpm install @openpanel/web
npm install @openpanel/web
```
### Initialize
### Step 2: Initialize
```tsx
import { Openpanel } from '@openpanel/web';
```js filename="op.ts"
import { OpenPanel } from '@openpanel/web';
const op = new Openpanel({
clientId: '{YOUR_CLIENT_ID}',
const op = new OpenPanel({
clientId: 'YOUR_CLIENT_ID',
trackScreenViews: true,
// trackAttributes: true,
// trackOutgoingLinks: true,
trackOutgoingLinks: true,
trackAttributes: true,
});
```
#### Config
#### Options
<SdkConfig />
<CommonSdkConfig />
<WebSdkConfig />
### Ready!
### Step 3: Usage
You're now ready to use the library.
```js filename="main.ts"
import { op } from './op.js';
```typescript
// Sends an event with payload foo: bar
op.event('my_event', { foo: 'bar' });
// Identify with profile id
op.setProfileId('123');
// or with additional data
op.setProfile({
profileId: '123',
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@openpanel.dev',
});
// Increment a property
op.increment('app_opened'); // increment by 1
op.increment('app_opened', 5); // increment by 5
// Decrement a property
op.decrement('app_opened'); // decrement by 1
op.decrement('app_opened', 5); // decrement by 5
op.track('my_event', { foo: 'bar' });
```
</Steps>
## Usage
### Track event
```typescript
op.event('my_event', { foo: 'bar' });
```
### Identify
#### Set Profile Id
Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior.
<PersonalDataWarning />
```typescript
const profileId = '123';
op.setProfileId(profileId);
```
#### Additional data
This method does the same as `setProfileId` but also allows you to update the profile with additional data.
<PersonalDataWarning />
```typescript
const profileId = '123';
op.setProfile({
profileId,
// firstName?: string;
// lastName?: string;
// email?: string;
// avatar?: string;
// properties?: Record<string, unknown>;
});
```
#### Increment property
Increment a property on the profile.
```typescript
// Increment by 1
op.increment('app_opened');
// Increment by 5
op.increment('app_opened', 5);
```
#### Decrement property
Decrement a property on the profile.
```typescript
// Increment by 1
op.decrement('app_opened');
// Increment by 5
op.decrement('app_opened', 5);
```
#### Clear / Logout
Clear the profile id and all the data.
```typescript
op.clear();
```
Refer to the [Javascript SDK](/docs/javascript#usage) for usage instructions.

View File

@@ -3,6 +3,14 @@ import { useRouter } from 'next/router';
import { useConfig } from 'nextra-theme-docs';
export default {
banner: {
key: '1.0-release',
text: (
<a href="/docs/migration/beta-v1">
🎉 We have released v1. Read migration guide if needed!
</a>
),
},
logo: (
<>
<Image

View File

@@ -1,6 +1,4 @@
'use client';
import React, { useEffect } from 'react';
import React from 'react';
import Script from 'next/script';
import type {
@@ -14,7 +12,7 @@ import type {
export * from '@openpanel/web';
const CDN_URL = 'https://openpanel.dev/op.js';
const CDN_URL = 'https://openpanel.dev/op1.js';
type OpenPanelComponentProps = Omit<OpenPanelOptions, 'filter'> & {
profileId?: string;

View File

@@ -67,12 +67,13 @@ export type OpenPanelOptions = {
sdkVersion?: string;
waitForProfile?: boolean;
filter?: (payload: TrackHandlerPayload) => boolean;
disable?: boolean;
};
export class OpenPanel {
api: Api;
profileId?: string;
global?: Record<string, any>;
global?: Record<string, unknown>;
queue: TrackHandlerPayload[] = [];
constructor(public options: OpenPanelOptions) {
@@ -94,6 +95,7 @@ export class OpenPanel {
});
}
// placeholder for future use
init() {
// empty
}
@@ -104,6 +106,10 @@ export class OpenPanel {
}
async send(payload: TrackHandlerPayload) {
if (this.options.disable) {
return Promise.resolve();
}
if (this.options.filter && !this.options.filter(payload)) {
return Promise.resolve();
}
@@ -115,7 +121,7 @@ export class OpenPanel {
return this.api.fetch('/track', payload);
}
setGlobalProperties(properties: Record<string, any>) {
setGlobalProperties(properties: Record<string, unknown>) {
this.global = {
...this.global,
...properties,
@@ -179,18 +185,18 @@ export class OpenPanel {
clear() {
this.profileId = undefined;
// session end?
// should we force a session end here?
}
flush() {
this.queue.forEach((item) => {
this.send({
...item,
// Not user why ts-expect-error is needed here
// Not sure why ts-expect-error is needed here
// @ts-expect-error
payload: {
...item.payload,
profileId: this.profileId,
profileId: item.payload.profileId ?? this.profileId,
},
});
});

View File

@@ -6,7 +6,8 @@ import type {
} from '@openpanel/sdk';
import { OpenPanel as OpenPanelBase } from '@openpanel/sdk';
export * from '@openpanel/sdk';
export type * from '@openpanel/sdk';
export { OpenPanel as OpenPanelBase } from '@openpanel/sdk';
export type OpenPanelOptions = OpenPanelBaseOptions & {
trackOutgoingLinks?: boolean;
@@ -129,20 +130,20 @@ export class OpenPanel extends OpenPanelBase {
const target = event.target as HTMLElement;
const btn = target.closest('button');
const anchor = target.closest('a');
const element = btn?.getAttribute('data-event')
const element = btn?.getAttribute('data-track')
? btn
: anchor?.getAttribute('data-event')
: anchor?.getAttribute('data-track')
? anchor
: null;
if (element) {
const properties: Record<string, unknown> = {};
for (const attr of element.attributes) {
if (attr.name.startsWith('data-') && attr.name !== 'data-event') {
if (attr.name.startsWith('data-') && attr.name !== 'data-track') {
properties[toCamelCase(attr.name.replace(/^data-/, ''))] =
attr.value;
}
}
const name = element.getAttribute('data-event');
const name = element.getAttribute('data-track');
if (name) {
super.track(name, properties);
}

View File

@@ -18,7 +18,7 @@ import { OpenPanel } from './index';
// @ts-expect-error
fn(...args);
} else {
console.warn(`op.js: ${t} is not a function`);
console.warn(`OpenPanel: ${t} is not a function`);
}
};

View File

@@ -228,7 +228,7 @@ function main() {
if (dependent === '@openpanel/web') {
execSync(
`cp ${workspacePath('packages/sdks/web/dist/src/tracker.global.js')} ${workspacePath('./apps/public/public/tracker.js')}`
`cp ${workspacePath('packages/sdks/web/dist/src/tracker.global.js')} ${workspacePath('./apps/public/public/op1.js')}`
);
}
});