a looooot
This commit is contained in:
1
apps/test/next-env.d.ts
vendored
1
apps/test/next-env.d.ts
vendored
@@ -1,5 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
/** @type {import("next").NextConfig} */
|
||||
const config = {
|
||||
reactStrictMode: false,
|
||||
transpilePackages: ['@mixan/types', '@mixan/sdk', '@mixan/web-sdk'],
|
||||
transpilePackages: [
|
||||
'@mixan/types',
|
||||
'@mixan/sdk',
|
||||
'@mixan/web-sdk',
|
||||
'@mixan/next',
|
||||
],
|
||||
eslint: { ignoreDuringBuilds: true },
|
||||
typescript: { ignoreBuildErrors: true },
|
||||
/**
|
||||
|
||||
@@ -11,11 +11,12 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "13.4",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"@mixan-test/next": "workspace:@mixan/next@*",
|
||||
"@mixan-test/sdk": "workspace:@mixan/sdk@*",
|
||||
"@mixan-test/sdk-web": "workspace:@mixan/sdk-web@*"
|
||||
"@mixan-test/sdk-web": "workspace:@mixan/sdk-web@*",
|
||||
"next": "~14.1.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mixan/eslint-config": "workspace:*",
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
"use strict";(()=>{function w(s){return Promise.all(Object.entries(s).map(async([t,e])=>[t,await e??""])).then(t=>Object.fromEntries(t))}function P(s){let t={"Content-Type":"application/json"};return{headers:t,async fetch(e,i,n){let o=`${s}${e}`,u,m=await w(t);return new Promise(c=>{let h=r=>{clearTimeout(u),fetch(o,{headers:m,method:"POST",body:JSON.stringify(i??{}),keepalive:!0,...n??{}}).then(async a=>{if(a.status!==200&&a.status!==202)return f(r,c);let g=await a.text();if(!g)return c(null);c(g)}).catch(()=>f(r,c))};function f(r,a){if(r>1)return a(null);u=setTimeout(()=>{h(r+1)},Math.pow(2,r)*500)}h(0)})}}}var l=class{options;api;state={properties:{}};constructor(t){this.options=t,this.api=P(t.url),this.api.headers["mixan-client-id"]=t.clientId,this.options.clientSecret&&(this.api.headers["mixan-client-secret"]=this.options.clientSecret)}init(t){this.state.properties=t??{}}setUser(t){this.api.fetch("/profile",{profileId:this.getProfileId(),...t,properties:{...this.state.properties,...t.properties}})}increment(t,e){this.api.fetch("/profile/increment",{property:t,value:e,profileId:this.getProfileId()})}decrement(t,e){this.api.fetch("/profile/decrement",{property:t,value:e,profileId:this.getProfileId()})}event(t,e){this.api.fetch("/event",{name:t,properties:{...this.state.properties,...e??{}},timestamp:this.timestamp(),profileId:this.getProfileId()}).then(i=>{this.options.setProfileId&&i&&this.options.setProfileId(i)})}setGlobalProperties(t){this.state.properties={...this.state.properties,...t}}clear(){this.state.profileId=void 0,this.options.removeProfileId&&this.options.removeProfileId()}timestamp(){return new Date().toISOString()}getProfileId(){if(this.state.profileId)return this.state.profileId;this.options.getProfileId&&(this.state.profileId=this.options.getProfileId()||void 0)}};var d=class extends l{lastPath="";constructor(t){super(t),this.isServer()||(this.setGlobalProperties({referrer:document.referrer}),this.options.trackOutgoingLinks&&this.trackOutgoingLinks(),this.options.trackScreenViews&&this.trackScreenViews())}isServer(){return typeof document>"u"}trackOutgoingLinks(){this.isServer()||document.addEventListener("click",t=>{let e=t.target,i=e.closest("a");if(i&&e){let n=i.getAttribute("href");n?.startsWith("http")&&super.event("link_out",{href:n,text:i.innerText||i.getAttribute("title")||e.getAttribute("alt")||e.getAttribute("title")})}})}trackScreenViews(){if(this.isServer())return;let t=history.pushState;history.pushState=function(...n){let o=t.apply(this,n);return window.dispatchEvent(new Event("pushstate")),window.dispatchEvent(new Event("locationchange")),o};let e=history.replaceState;history.replaceState=function(...n){let o=e.apply(this,n);return window.dispatchEvent(new Event("replacestate")),window.dispatchEvent(new Event("locationchange")),o},window.addEventListener("popstate",()=>window.dispatchEvent(new Event("locationchange"))),this.options.hash?window.addEventListener("hashchange",()=>this.screenView()):window.addEventListener("locationchange",()=>this.screenView()),this.screenView()}screenView(t){if(this.isServer())return;let e=window.location.href;this.lastPath!==e&&(this.lastPath=e,super.event("screen_view",{...t??{},path:e,title:document.title}))}};var p=document.currentScript;p&&(window.openpanel=new d({url:p?.getAttribute("data-url"),clientId:p?.getAttribute("data-client-id"),trackOutgoingLinks:!!p?.getAttribute("data-track-outgoing-links"),trackScreenViews:!!p?.getAttribute("data-track-screen-views")}));})();
|
||||
"use strict";(()=>{function v(r){return Promise.all(Object.entries(r).map(async([t,e])=>[t,await e??""])).then(t=>Object.fromEntries(t))}function m(r){let t={"Content-Type":"application/json"};return{headers:t,async fetch(e,i,n){let s=`${r}${e}`,c,l=await v(t);return new Promise(o=>{let h=a=>{clearTimeout(c),fetch(s,{headers:l,method:"POST",body:JSON.stringify(i??{}),keepalive:!0,...n??{}}).then(async p=>{if(p.status!==200&&p.status!==202)return f(a,o);let g=await p.text();if(!g)return o(null);o(g)}).catch(()=>f(a,o))};function f(a,p){if(a>1)return p(null);c=setTimeout(()=>{h(a+1)},Math.pow(2,a)*500)}h(0)})}}}var d=class{options;api;state={properties:{}};constructor(t){this.options=t,this.api=m(t.url),this.api.headers["mixan-client-id"]=t.clientId,this.options.clientSecret&&(this.api.headers["mixan-client-secret"]=this.options.clientSecret)}init(t){this.state.properties=t??{}}setProfileId(t){this.state.profileId=t}setProfile(t){this.setProfileId(t.profileId),this.api.fetch("/profile",{...t,properties:{...this.state.properties,...t.properties}})}increment(t,e,i){let n=i?.profileId??this.state.profileId;if(!n)return console.log("No profile id");this.api.fetch("/profile/increment",{profileId:n,property:t,value:e})}decrement(t,e,i){let n=i?.profileId??this.state.profileId;if(!n)return console.log("No profile id");this.api.fetch("/profile/decrement",{profileId:n,property:t,value:e})}event(t,e){let i=e?.profileId??this.state.profileId;delete e?.profileId,this.api.fetch("/event",{name:t,properties:{...this.state.properties,...e??{}},timestamp:this.timestamp(),deviceId:this.getDeviceId(),profileId:i}).then(n=>{this.options.setDeviceId&&n&&this.options.setDeviceId(n)})}setGlobalProperties(t){this.state.properties={...this.state.properties,...t}}clear(){this.state.properties={},this.state.deviceId=void 0,this.options.removeDeviceId&&this.options.removeDeviceId()}timestamp(){return new Date().toISOString()}getDeviceId(){if(this.state.deviceId)return this.state.deviceId;this.options.getDeviceId&&(this.state.deviceId=this.options.getDeviceId()||void 0)}};function b(r){return r.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_",""))}var u=class extends d{lastPath="";constructor(t){super(t),this.isServer()||(this.setGlobalProperties({referrer:document.referrer}),this.options.trackOutgoingLinks&&this.trackOutgoingLinks(),this.options.trackScreenViews&&this.trackScreenViews(),this.options.trackAttributes&&this.trackAttributes())}isServer(){return typeof document>"u"}trackOutgoingLinks(){this.isServer()||document.addEventListener("click",t=>{let e=t.target,i=e.closest("a");if(i&&e){let n=i.getAttribute("href");n?.startsWith("http")&&super.event("link_out",{href:n,text:i.innerText||i.getAttribute("title")||e.getAttribute("alt")||e.getAttribute("title")})}})}trackScreenViews(){if(this.isServer())return;let t=history.pushState;history.pushState=function(...n){let s=t.apply(this,n);return window.dispatchEvent(new Event("pushstate")),window.dispatchEvent(new Event("locationchange")),s};let e=history.replaceState;history.replaceState=function(...n){let s=e.apply(this,n);return window.dispatchEvent(new Event("replacestate")),window.dispatchEvent(new Event("locationchange")),s},window.addEventListener("popstate",()=>window.dispatchEvent(new Event("locationchange"))),this.options.hash?window.addEventListener("hashchange",()=>this.screenView()):window.addEventListener("locationchange",()=>this.screenView()),setTimeout(()=>{this.screenView()},50)}trackAttributes(){this.isServer()||document.addEventListener("click",t=>{let e=t.target,i=e.closest("button"),n=e.closest("button"),s=i?.getAttribute("data-event")?i:n?.getAttribute("data-event")?n:null;if(s){let c={};for(let o of s.attributes)o.name.startsWith("data-")&&o.name!=="data-event"&&(c[b(o.name.replace(/^data-/,""))]=o.value);let l=s.getAttribute("data-event");l&&super.event(l,c)}})}screenView(t){if(this.isServer())return;let e=window.location.href;this.lastPath!==e&&(this.lastPath=e,super.event("screen_view",{...t??{},path:e,title:document.title}))}};(r=>{if(r.op&&"q"in r.op){let t=r.op.q||[],e=new u(t.shift()[1]);t.forEach(i=>{i[0]in e&&e[i[0]](...i.slice(1))}),r.op=(i,...n)=>{let s=e[i].bind(e);typeof s=="function"&&s(...n)}}})(window);})();
|
||||
//# sourceMappingURL=cdn.global.js.map
|
||||
12
apps/test/src/app/app-dir/page.component.tsx
Normal file
12
apps/test/src/app/app-dir/page.component.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
'use client';
|
||||
|
||||
export default function TestPage({ triggerEvent }: { triggerEvent: any }) {
|
||||
return (
|
||||
<>
|
||||
<button onClick={() => triggerEvent()}>Event (server action)</button>
|
||||
<button data-event="yolo" data-yolo="123" data-hihi="taaa-daaaaa">
|
||||
Event (data-attributes)
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
55
apps/test/src/app/app-dir/page.tsx
Normal file
55
apps/test/src/app/app-dir/page.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import { OpenpanelProvider, SetProfileId, trackEvent } from '@mixan-test/next';
|
||||
import { Mixan as Openpanel } from '@mixan-test/sdk';
|
||||
|
||||
const opServer = new Openpanel({
|
||||
clientId: '4c9a28cb-73c3-429f-beaf-4b3fe91352ea',
|
||||
clientSecret: '2701ada9-fcbf-414a-ac94-9511949ee44d',
|
||||
url: 'https://api.openpanel.dev',
|
||||
});
|
||||
|
||||
export default function Page() {
|
||||
// Track event in server actions
|
||||
async function create() {
|
||||
'use server';
|
||||
opServer.event('some-event', {
|
||||
profileId: '1234',
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* In layout.tsx (app dir) or _app.tsx (pages) */}
|
||||
<OpenpanelProvider
|
||||
clientId="0acce97f-1126-4439-b7ee-5d384e2fc94b"
|
||||
url="https://api.openpanel.dev"
|
||||
trackScreenViews
|
||||
trackAttributes
|
||||
trackOutgoingLinks
|
||||
/>
|
||||
|
||||
{/* Provide user id in React Server Components */}
|
||||
<SetProfileId value="1234" />
|
||||
|
||||
<button
|
||||
onClick={() =>
|
||||
trackEvent('some-event', {
|
||||
bar: 'bar',
|
||||
foo: 'foo',
|
||||
revenue: 1000,
|
||||
})
|
||||
}
|
||||
>
|
||||
Track event with method
|
||||
</button>
|
||||
|
||||
<button
|
||||
data-event="some-event"
|
||||
data-bar="bar"
|
||||
data-foo="foo"
|
||||
data-revenue="1000"
|
||||
>
|
||||
Track event with attributes
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
22
apps/test/src/app/layout.tsx
Normal file
22
apps/test/src/app/layout.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { OpenpanelProvider } from '@mixan-test/next';
|
||||
|
||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
<body>
|
||||
<OpenpanelProvider
|
||||
clientId="0acce97f-1126-4439-b7ee-5d384e2fc94b"
|
||||
url="http://localhost:3333"
|
||||
trackScreenViews
|
||||
trackAttributes
|
||||
trackOutgoingLinks
|
||||
/>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
import { useEffect } from 'react';
|
||||
// import { mixan } from '@/analytics';
|
||||
import { OpenpanelProvider } from '@mixan-test/next';
|
||||
import type { AppProps } from 'next/app';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function MyApp({ Component, pageProps }: AppProps) {
|
||||
const router = useRouter();
|
||||
// useEffect(() => {
|
||||
// mixan.screenView();
|
||||
// return router.events.on('routeChangeComplete', () => {
|
||||
// mixan.screenView();
|
||||
// });
|
||||
// }, []);
|
||||
return <Component {...pageProps} />;
|
||||
return (
|
||||
<>
|
||||
<OpenpanelProvider
|
||||
clientId="0acce97f-1126-4439-b7ee-5d384e2fc94b"
|
||||
url="http://localhost:3333"
|
||||
trackScreenViews
|
||||
/>
|
||||
<Component {...pageProps} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Head, Html, Main, NextScript } from 'next/document';
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html>
|
||||
<Head>
|
||||
<script
|
||||
async
|
||||
src="/op.js"
|
||||
data-url="http://localhost:3333"
|
||||
data-client-id="0acce97f-1126-4439-b7ee-5d384e2fc94b"
|
||||
data-track-screen-views="1"
|
||||
data-track-outgoing-links="1"
|
||||
/>
|
||||
</Head>
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
@@ -1,17 +1,68 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
clear,
|
||||
decrement,
|
||||
increment,
|
||||
setProfile,
|
||||
trackEvent,
|
||||
} from '@mixan-test/next';
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Test() {
|
||||
const [id, setId] = useState('');
|
||||
const [auth, setAuth] = useState<string | null>(null);
|
||||
|
||||
function handleLogin() {
|
||||
if (id) {
|
||||
localStorage.setItem('auth', id);
|
||||
setAuth(id);
|
||||
}
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
localStorage.removeItem('auth');
|
||||
setAuth(null);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setAuth(localStorage.getItem('auth') ?? null);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('auth', auth);
|
||||
|
||||
if (auth) {
|
||||
console.log('set profile?', auth);
|
||||
|
||||
setProfile({
|
||||
profileId: auth,
|
||||
});
|
||||
} else {
|
||||
clear();
|
||||
}
|
||||
}, [auth]);
|
||||
|
||||
if (auth === null) {
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Login with user id"
|
||||
onChange={(e) => setId(e.target.value)}
|
||||
/>
|
||||
<button onClick={handleLogin}>Login</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Link href="/">Home</Link>
|
||||
<button
|
||||
onClick={() => {
|
||||
// @ts-expect-error
|
||||
window.openpanel.setUser({
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
email: 'john.doe@gmail.com',
|
||||
id: '1234',
|
||||
setProfile({
|
||||
firstName: 'Maja',
|
||||
lastName: 'Klara',
|
||||
profileId: auth,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -19,16 +70,14 @@ export default function Test() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
// @ts-expect-error
|
||||
window.openpanel.increment('app_open', 1);
|
||||
increment('app_open', 1);
|
||||
}}
|
||||
>
|
||||
Increment
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
// @ts-expect-error
|
||||
window.openpanel.decrement('app_open', 1);
|
||||
decrement('app_open', 1);
|
||||
}}
|
||||
>
|
||||
Decrement
|
||||
@@ -43,8 +92,7 @@ export default function Test() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
// @ts-ignore
|
||||
window.openpanel.event('custom_click', {
|
||||
trackEvent('custom_click', {
|
||||
custom_string: 'test',
|
||||
custom_number: 1,
|
||||
});
|
||||
@@ -52,14 +100,7 @@ export default function Test() {
|
||||
>
|
||||
Trigger event
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
// @ts-expect-error
|
||||
window.openpanel.clear();
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
<button onClick={handleLogout}>Logout</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,15 +3,23 @@
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
|
||||
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json",
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"include": [".", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": [
|
||||
".",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user