shopcircle-orbit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # shopcircle-orbit
2
+
3
+ Lightweight analytics SDK for [ShopCircle Orbit](https://github.com/shopcircle/orbit). Track events, identify users, and measure engagement with zero dependencies.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install shopcircle-orbit
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { ShopCircleOrbit } from 'shopcircle-orbit';
15
+
16
+ const orbit = new ShopCircleOrbit({
17
+ clientId: 'your-client-id',
18
+ apiUrl: 'https://analytics.yoursite.com',
19
+ trackScreenViews: true,
20
+ trackOutgoingLinks: true,
21
+ trackAttributes: true,
22
+ });
23
+
24
+ // Track a custom event
25
+ orbit.track('button_clicked', { label: 'Sign Up', variant: 'primary' });
26
+
27
+ // Identify a user
28
+ orbit.identify('user_123', {
29
+ firstName: 'John',
30
+ email: 'john@example.com',
31
+ });
32
+
33
+ // Reset identity (e.g. on logout)
34
+ orbit.reset();
35
+ ```
36
+
37
+ ## Script Tag
38
+
39
+ No build step required:
40
+
41
+ ```html
42
+ <script type="module">
43
+ import { ShopCircleOrbit } from 'https://esm.sh/shopcircle-orbit';
44
+
45
+ const orbit = new ShopCircleOrbit({
46
+ clientId: 'your-client-id',
47
+ apiUrl: 'https://analytics.yoursite.com',
48
+ trackScreenViews: true,
49
+ });
50
+
51
+ window.orbit = orbit;
52
+ </script>
53
+ ```
54
+
55
+ ## React / Next.js
56
+
57
+ ```tsx
58
+ import { ShopCircleOrbit } from 'shopcircle-orbit';
59
+ import { createContext, useContext, useRef } from 'react';
60
+
61
+ const OrbitContext = createContext<ShopCircleOrbit | null>(null);
62
+
63
+ export function OrbitProvider({ children }: { children: React.ReactNode }) {
64
+ const orbitRef = useRef(
65
+ new ShopCircleOrbit({
66
+ clientId: 'your-client-id',
67
+ apiUrl: 'https://analytics.yoursite.com',
68
+ trackScreenViews: true,
69
+ trackOutgoingLinks: true,
70
+ })
71
+ );
72
+
73
+ return (
74
+ <OrbitContext.Provider value={orbitRef.current}>
75
+ {children}
76
+ </OrbitContext.Provider>
77
+ );
78
+ }
79
+
80
+ export const useOrbit = () => {
81
+ const ctx = useContext(OrbitContext);
82
+ if (!ctx) throw new Error('Wrap your app with <OrbitProvider>');
83
+ return ctx;
84
+ };
85
+ ```
86
+
87
+ ## Options
88
+
89
+ | Option | Type | Default | Description |
90
+ |---|---|---|---|
91
+ | `clientId` | `string` | *required* | Your client ID from the Orbit dashboard |
92
+ | `apiUrl` | `string` | `""` | Base URL of your Orbit instance |
93
+ | `trackScreenViews` | `boolean` | `true` | Auto-track page views and SPA navigations |
94
+ | `trackOutgoingLinks` | `boolean` | `false` | Auto-track clicks on external links |
95
+ | `trackAttributes` | `boolean` | `false` | Auto-track elements with `data-orbit-*` attributes |
96
+
97
+ ## Data Attributes
98
+
99
+ Track events declaratively with HTML attributes:
100
+
101
+ ```html
102
+ <button data-orbit-event="cta_clicked" data-orbit-variant="hero" data-orbit-plan="pro">
103
+ Get Started
104
+ </button>
105
+ ```
106
+
107
+ ## API
108
+
109
+ | Method | Description |
110
+ |---|---|
111
+ | `track(name, properties?)` | Track a custom event |
112
+ | `identify(profileId, traits?)` | Identify a user |
113
+ | `reset()` | Clear current user identity |
114
+ | `destroy()` | Remove all event listeners |
115
+
116
+ ## License
117
+
118
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var l=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var u=(r,t)=>{for(var e in t)l(r,e,{get:t[e],enumerable:!0})},f=(r,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of h(t))!d.call(r,n)&&n!==e&&l(r,n,{get:()=>t[n],enumerable:!(i=p(t,n))||i.enumerable});return r};var g=r=>f(l({},"__esModule",{value:!0}),r);var m={};u(m,{ShopCircleOrbit:()=>s,createOrbit:()=>w,default:()=>y});module.exports=g(m);var v="shopcircle-orbit",k="1.0.0",s=class{constructor(t){this.profileId=null;this.queue=[];this.flushing=!1;this.destroyed=!1;this.popstateHandler=null;this.clickHandler=null;this.lastPath=null;this.originalPushState=null;this.originalReplaceState=null;if(this.clientId=t.clientId,this.apiUrl=(t.apiUrl||"").replace(/\/$/,""),this.trackScreenViews=t.trackScreenViews??!0,this.trackOutgoingLinks=t.trackOutgoingLinks??!1,this.trackAttributes=t.trackAttributes??!1,!this.clientId){console.warn("[shopcircle-orbit] Missing clientId");return}typeof window<"u"&&this.setupAutoTracking()}track(t,e){this.enqueue(()=>this.send({type:"track",payload:{name:t,properties:{...this.getPageContext(),...e}}}))}identify(t,e){this.profileId=t;let{firstName:i,lastName:n,email:a,avatar:o,...c}=e||{};this.enqueue(()=>this.send({type:"identify",payload:{profileId:t,firstName:i,lastName:n,email:a,avatar:o,properties:Object.keys(c).length>0?c:void 0}}))}reset(){this.profileId=null}destroy(){this.destroyed=!0,!(typeof window>"u")&&(this.popstateHandler&&window.removeEventListener("popstate",this.popstateHandler),this.clickHandler&&document.removeEventListener("click",this.clickHandler,!0),this.originalPushState&&(history.pushState=this.originalPushState),this.originalReplaceState&&(history.replaceState=this.originalReplaceState))}setupAutoTracking(){this.trackScreenViews&&(this.trackScreenView(),this.observeNavigation()),(this.trackOutgoingLinks||this.trackAttributes)&&this.observeClicks()}trackScreenView(){let t=window.location.pathname+window.location.search;t!==this.lastPath&&(this.lastPath=t,this.track("screen_view",{path:window.location.pathname,origin:window.location.origin,referrer:document.referrer||void 0,referrer_name:document.referrer?this.extractDomain(document.referrer):void 0,title:document.title||void 0}))}observeNavigation(){this.popstateHandler=()=>this.trackScreenView(),window.addEventListener("popstate",this.popstateHandler),this.originalPushState=history.pushState.bind(history),this.originalReplaceState=history.replaceState.bind(history),history.pushState=(...t)=>{this.originalPushState(...t),setTimeout(()=>this.trackScreenView(),0)},history.replaceState=(...t)=>{this.originalReplaceState(...t),setTimeout(()=>this.trackScreenView(),0)}}observeClicks(){this.clickHandler=t=>{let e=t.target?.closest?.("a, [data-orbit-event]");if(e){if(this.trackOutgoingLinks&&e.tagName==="A"){let i=e.href;i&&this.isExternalLink(i)&&this.track("outgoing_link",{href:i,text:(e.textContent||"").trim().substring(0,200)})}if(this.trackAttributes){let i=e.getAttribute("data-orbit-event");if(i){let n={};for(let a of Array.from(e.attributes))if(a.name.startsWith("data-orbit-")&&a.name!=="data-orbit-event"){let o=a.name.replace("data-orbit-","");n[o]=a.value}this.track(i,n)}}}},document.addEventListener("click",this.clickHandler,!0)}async send(t){if(this.destroyed)return;this.profileId&&!t.payload.profileId&&(t.payload.profileId=this.profileId);let e=`${this.apiUrl}/api/track`;try{await fetch(e,{method:"POST",headers:{"Content-Type":"application/json","openpanel-client-id":this.clientId,"openpanel-sdk-name":v,"openpanel-sdk-version":k},body:JSON.stringify(t),keepalive:!0})}catch{}}enqueue(t){this.queue.push(t),this.flush()}async flush(){if(!this.flushing){for(this.flushing=!0;this.queue.length>0;)await this.queue.shift()();this.flushing=!1}}getPageContext(){return typeof window>"u"?{}:{path:window.location.pathname,origin:window.location.origin}}isExternalLink(t){try{return new URL(t).origin!==window.location.origin}catch{return!1}}extractDomain(t){try{return new URL(t).hostname}catch{return t}}};function w(r){return new s(r)}var y=s;0&&(module.exports={ShopCircleOrbit,createOrbit});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["const SDK_NAME = \"shopcircle-orbit\"\nconst SDK_VERSION = \"1.0.0\"\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface OrbitOptions {\n /** Your client ID from the analytics dashboard */\n clientId: string\n /** Base URL of your analytics panel (e.g. \"https://analytics.yoursite.com\") */\n apiUrl?: string\n /** Automatically track page/screen views (default: true) */\n trackScreenViews?: boolean\n /** Automatically track clicks on outgoing links (default: false) */\n trackOutgoingLinks?: boolean\n /** Automatically track data-orbit-* attributes on clicked elements (default: false) */\n trackAttributes?: boolean\n}\n\nexport interface IdentifyTraits {\n firstName?: string\n lastName?: string\n email?: string\n avatar?: string\n [key: string]: unknown\n}\n\nexport type Properties = Record<string, unknown>\n\n// ─── SDK ──────────────────────────────────────────────────────────────────────\n\nexport class ShopCircleOrbit {\n private clientId: string\n private apiUrl: string\n private trackScreenViews: boolean\n private trackOutgoingLinks: boolean\n private trackAttributes: boolean\n private profileId: string | null = null\n private queue: Array<() => Promise<void>> = []\n private flushing = false\n private destroyed = false\n\n // Stored references for cleanup\n private popstateHandler: (() => void) | null = null\n private clickHandler: ((e: MouseEvent) => void) | null = null\n private lastPath: string | null = null\n private originalPushState: typeof history.pushState | null = null\n private originalReplaceState: typeof history.replaceState | null = null\n\n constructor(options: OrbitOptions) {\n this.clientId = options.clientId\n this.apiUrl = (options.apiUrl || \"\").replace(/\\/$/, \"\")\n this.trackScreenViews = options.trackScreenViews ?? true\n this.trackOutgoingLinks = options.trackOutgoingLinks ?? false\n this.trackAttributes = options.trackAttributes ?? false\n\n if (!this.clientId) {\n console.warn(\"[shopcircle-orbit] Missing clientId\")\n return\n }\n\n if (typeof window !== \"undefined\") {\n this.setupAutoTracking()\n }\n }\n\n // ─── Public API ───────────────────────────────────────────────────────\n\n /**\n * Track a custom event with optional properties.\n *\n * @example\n * orbit.track(\"button_clicked\", { label: \"Sign Up\", variant: \"primary\" })\n */\n track(name: string, properties?: Properties): void {\n this.enqueue(() =>\n this.send({\n type: \"track\",\n payload: {\n name,\n properties: {\n ...this.getPageContext(),\n ...properties,\n },\n },\n })\n )\n }\n\n /**\n * Identify a user. Subsequent events will be associated with this profile.\n *\n * @example\n * orbit.identify(\"user_123\", { firstName: \"John\", email: \"john@example.com\" })\n */\n identify(profileId: string, traits?: IdentifyTraits): void {\n this.profileId = profileId\n\n const { firstName, lastName, email, avatar, ...rest } = traits || {}\n\n this.enqueue(() =>\n this.send({\n type: \"identify\",\n payload: {\n profileId,\n firstName,\n lastName,\n email,\n avatar,\n properties: Object.keys(rest).length > 0 ? rest : undefined,\n },\n })\n )\n }\n\n /**\n * Reset the current user identity (e.g. on logout).\n */\n reset(): void {\n this.profileId = null\n }\n\n /**\n * Clean up event listeners. Call this when unmounting in SPA frameworks.\n */\n destroy(): void {\n this.destroyed = true\n if (typeof window === \"undefined\") return\n\n if (this.popstateHandler) {\n window.removeEventListener(\"popstate\", this.popstateHandler)\n }\n if (this.clickHandler) {\n document.removeEventListener(\"click\", this.clickHandler, true)\n }\n if (this.originalPushState) {\n history.pushState = this.originalPushState\n }\n if (this.originalReplaceState) {\n history.replaceState = this.originalReplaceState\n }\n }\n\n // ─── Auto-tracking ────────────────────────────────────────────────────\n\n private setupAutoTracking(): void {\n if (this.trackScreenViews) {\n this.trackScreenView()\n this.observeNavigation()\n }\n\n if (this.trackOutgoingLinks || this.trackAttributes) {\n this.observeClicks()\n }\n }\n\n private trackScreenView(): void {\n const path = window.location.pathname + window.location.search\n if (path === this.lastPath) return\n this.lastPath = path\n\n this.track(\"screen_view\", {\n path: window.location.pathname,\n origin: window.location.origin,\n referrer: document.referrer || undefined,\n referrer_name: document.referrer\n ? this.extractDomain(document.referrer)\n : undefined,\n title: document.title || undefined,\n })\n }\n\n private observeNavigation(): void {\n // Listen for popstate (back/forward)\n this.popstateHandler = () => this.trackScreenView()\n window.addEventListener(\"popstate\", this.popstateHandler)\n\n // Monkey-patch pushState/replaceState to detect SPA navigations\n this.originalPushState = history.pushState.bind(history)\n this.originalReplaceState = history.replaceState.bind(history)\n\n history.pushState = (...args) => {\n this.originalPushState!(...args)\n // Small delay to let the URL update\n setTimeout(() => this.trackScreenView(), 0)\n }\n\n history.replaceState = (...args) => {\n this.originalReplaceState!(...args)\n setTimeout(() => this.trackScreenView(), 0)\n }\n }\n\n private observeClicks(): void {\n this.clickHandler = (e: MouseEvent) => {\n const target = (e.target as Element)?.closest?.(\"a, [data-orbit-event]\")\n if (!target) return\n\n // Track outgoing links\n if (this.trackOutgoingLinks && target.tagName === \"A\") {\n const href = (target as HTMLAnchorElement).href\n if (href && this.isExternalLink(href)) {\n this.track(\"outgoing_link\", {\n href,\n text: (target.textContent || \"\").trim().substring(0, 200),\n })\n }\n }\n\n // Track data-orbit-* attributes\n if (this.trackAttributes) {\n const eventName = target.getAttribute(\"data-orbit-event\")\n if (eventName) {\n const props: Properties = {}\n for (const attr of Array.from(target.attributes)) {\n if (attr.name.startsWith(\"data-orbit-\") && attr.name !== \"data-orbit-event\") {\n const key = attr.name.replace(\"data-orbit-\", \"\")\n props[key] = attr.value\n }\n }\n this.track(eventName, props)\n }\n }\n }\n document.addEventListener(\"click\", this.clickHandler, true)\n }\n\n // ─── Network ──────────────────────────────────────────────────────────\n\n private async send(body: {\n type: string\n payload: Record<string, unknown>\n }): Promise<void> {\n if (this.destroyed) return\n\n // Inject profileId if set\n if (this.profileId && !body.payload.profileId) {\n body.payload.profileId = this.profileId\n }\n\n const url = `${this.apiUrl}/api/track`\n\n try {\n await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"openpanel-client-id\": this.clientId,\n \"openpanel-sdk-name\": SDK_NAME,\n \"openpanel-sdk-version\": SDK_VERSION,\n },\n body: JSON.stringify(body),\n keepalive: true,\n })\n } catch {\n // Silently fail - analytics should never break the app\n }\n }\n\n // ─── Queue ────────────────────────────────────────────────────────────\n\n private enqueue(fn: () => Promise<void>): void {\n this.queue.push(fn)\n this.flush()\n }\n\n private async flush(): Promise<void> {\n if (this.flushing) return\n this.flushing = true\n\n while (this.queue.length > 0) {\n const fn = this.queue.shift()!\n await fn()\n }\n\n this.flushing = false\n }\n\n // ─── Helpers ──────────────────────────────────────────────────────────\n\n private getPageContext(): Properties {\n if (typeof window === \"undefined\") return {}\n return {\n path: window.location.pathname,\n origin: window.location.origin,\n }\n }\n\n private isExternalLink(href: string): boolean {\n try {\n return new URL(href).origin !== window.location.origin\n } catch {\n return false\n }\n }\n\n private extractDomain(url: string): string {\n try {\n return new URL(url).hostname\n } catch {\n return url\n }\n }\n}\n\n// ─── Convenience factory ──────────────────────────────────────────────────────\n\n/**\n * Create a new ShopCircleOrbit instance.\n *\n * @example\n * import { createOrbit } from \"shopcircle-orbit\"\n *\n * const orbit = createOrbit({\n * clientId: \"your-client-id\",\n * apiUrl: \"https://analytics.yoursite.com\",\n * })\n *\n * orbit.track(\"purchase\", { amount: 99.99 })\n */\nexport function createOrbit(options: OrbitOptions): ShopCircleOrbit {\n return new ShopCircleOrbit(options)\n}\n\n// Default export for convenience\nexport default ShopCircleOrbit\n"],"mappings":"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","names":["index_exports","__export","ShopCircleOrbit","createOrbit","index_default","__toCommonJS","SDK_NAME","SDK_VERSION","options","name","properties","profileId","traits","firstName","lastName","email","avatar","rest","path","args","e","target","href","eventName","props","attr","key","body","url","fn"]}
@@ -0,0 +1,85 @@
1
+ interface OrbitOptions {
2
+ /** Your client ID from the analytics dashboard */
3
+ clientId: string;
4
+ /** Base URL of your analytics panel (e.g. "https://analytics.yoursite.com") */
5
+ apiUrl?: string;
6
+ /** Automatically track page/screen views (default: true) */
7
+ trackScreenViews?: boolean;
8
+ /** Automatically track clicks on outgoing links (default: false) */
9
+ trackOutgoingLinks?: boolean;
10
+ /** Automatically track data-orbit-* attributes on clicked elements (default: false) */
11
+ trackAttributes?: boolean;
12
+ }
13
+ interface IdentifyTraits {
14
+ firstName?: string;
15
+ lastName?: string;
16
+ email?: string;
17
+ avatar?: string;
18
+ [key: string]: unknown;
19
+ }
20
+ type Properties = Record<string, unknown>;
21
+ declare class ShopCircleOrbit {
22
+ private clientId;
23
+ private apiUrl;
24
+ private trackScreenViews;
25
+ private trackOutgoingLinks;
26
+ private trackAttributes;
27
+ private profileId;
28
+ private queue;
29
+ private flushing;
30
+ private destroyed;
31
+ private popstateHandler;
32
+ private clickHandler;
33
+ private lastPath;
34
+ private originalPushState;
35
+ private originalReplaceState;
36
+ constructor(options: OrbitOptions);
37
+ /**
38
+ * Track a custom event with optional properties.
39
+ *
40
+ * @example
41
+ * orbit.track("button_clicked", { label: "Sign Up", variant: "primary" })
42
+ */
43
+ track(name: string, properties?: Properties): void;
44
+ /**
45
+ * Identify a user. Subsequent events will be associated with this profile.
46
+ *
47
+ * @example
48
+ * orbit.identify("user_123", { firstName: "John", email: "john@example.com" })
49
+ */
50
+ identify(profileId: string, traits?: IdentifyTraits): void;
51
+ /**
52
+ * Reset the current user identity (e.g. on logout).
53
+ */
54
+ reset(): void;
55
+ /**
56
+ * Clean up event listeners. Call this when unmounting in SPA frameworks.
57
+ */
58
+ destroy(): void;
59
+ private setupAutoTracking;
60
+ private trackScreenView;
61
+ private observeNavigation;
62
+ private observeClicks;
63
+ private send;
64
+ private enqueue;
65
+ private flush;
66
+ private getPageContext;
67
+ private isExternalLink;
68
+ private extractDomain;
69
+ }
70
+ /**
71
+ * Create a new ShopCircleOrbit instance.
72
+ *
73
+ * @example
74
+ * import { createOrbit } from "shopcircle-orbit"
75
+ *
76
+ * const orbit = createOrbit({
77
+ * clientId: "your-client-id",
78
+ * apiUrl: "https://analytics.yoursite.com",
79
+ * })
80
+ *
81
+ * orbit.track("purchase", { amount: 99.99 })
82
+ */
83
+ declare function createOrbit(options: OrbitOptions): ShopCircleOrbit;
84
+
85
+ export { type IdentifyTraits, type OrbitOptions, type Properties, ShopCircleOrbit, createOrbit, ShopCircleOrbit as default };
@@ -0,0 +1,85 @@
1
+ interface OrbitOptions {
2
+ /** Your client ID from the analytics dashboard */
3
+ clientId: string;
4
+ /** Base URL of your analytics panel (e.g. "https://analytics.yoursite.com") */
5
+ apiUrl?: string;
6
+ /** Automatically track page/screen views (default: true) */
7
+ trackScreenViews?: boolean;
8
+ /** Automatically track clicks on outgoing links (default: false) */
9
+ trackOutgoingLinks?: boolean;
10
+ /** Automatically track data-orbit-* attributes on clicked elements (default: false) */
11
+ trackAttributes?: boolean;
12
+ }
13
+ interface IdentifyTraits {
14
+ firstName?: string;
15
+ lastName?: string;
16
+ email?: string;
17
+ avatar?: string;
18
+ [key: string]: unknown;
19
+ }
20
+ type Properties = Record<string, unknown>;
21
+ declare class ShopCircleOrbit {
22
+ private clientId;
23
+ private apiUrl;
24
+ private trackScreenViews;
25
+ private trackOutgoingLinks;
26
+ private trackAttributes;
27
+ private profileId;
28
+ private queue;
29
+ private flushing;
30
+ private destroyed;
31
+ private popstateHandler;
32
+ private clickHandler;
33
+ private lastPath;
34
+ private originalPushState;
35
+ private originalReplaceState;
36
+ constructor(options: OrbitOptions);
37
+ /**
38
+ * Track a custom event with optional properties.
39
+ *
40
+ * @example
41
+ * orbit.track("button_clicked", { label: "Sign Up", variant: "primary" })
42
+ */
43
+ track(name: string, properties?: Properties): void;
44
+ /**
45
+ * Identify a user. Subsequent events will be associated with this profile.
46
+ *
47
+ * @example
48
+ * orbit.identify("user_123", { firstName: "John", email: "john@example.com" })
49
+ */
50
+ identify(profileId: string, traits?: IdentifyTraits): void;
51
+ /**
52
+ * Reset the current user identity (e.g. on logout).
53
+ */
54
+ reset(): void;
55
+ /**
56
+ * Clean up event listeners. Call this when unmounting in SPA frameworks.
57
+ */
58
+ destroy(): void;
59
+ private setupAutoTracking;
60
+ private trackScreenView;
61
+ private observeNavigation;
62
+ private observeClicks;
63
+ private send;
64
+ private enqueue;
65
+ private flush;
66
+ private getPageContext;
67
+ private isExternalLink;
68
+ private extractDomain;
69
+ }
70
+ /**
71
+ * Create a new ShopCircleOrbit instance.
72
+ *
73
+ * @example
74
+ * import { createOrbit } from "shopcircle-orbit"
75
+ *
76
+ * const orbit = createOrbit({
77
+ * clientId: "your-client-id",
78
+ * apiUrl: "https://analytics.yoursite.com",
79
+ * })
80
+ *
81
+ * orbit.track("purchase", { amount: 99.99 })
82
+ */
83
+ declare function createOrbit(options: OrbitOptions): ShopCircleOrbit;
84
+
85
+ export { type IdentifyTraits, type OrbitOptions, type Properties, ShopCircleOrbit, createOrbit, ShopCircleOrbit as default };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ var c="shopcircle-orbit",p="1.0.0",a=class{constructor(t){this.profileId=null;this.queue=[];this.flushing=!1;this.destroyed=!1;this.popstateHandler=null;this.clickHandler=null;this.lastPath=null;this.originalPushState=null;this.originalReplaceState=null;if(this.clientId=t.clientId,this.apiUrl=(t.apiUrl||"").replace(/\/$/,""),this.trackScreenViews=t.trackScreenViews??!0,this.trackOutgoingLinks=t.trackOutgoingLinks??!1,this.trackAttributes=t.trackAttributes??!1,!this.clientId){console.warn("[shopcircle-orbit] Missing clientId");return}typeof window<"u"&&this.setupAutoTracking()}track(t,e){this.enqueue(()=>this.send({type:"track",payload:{name:t,properties:{...this.getPageContext(),...e}}}))}identify(t,e){this.profileId=t;let{firstName:i,lastName:n,email:r,avatar:s,...l}=e||{};this.enqueue(()=>this.send({type:"identify",payload:{profileId:t,firstName:i,lastName:n,email:r,avatar:s,properties:Object.keys(l).length>0?l:void 0}}))}reset(){this.profileId=null}destroy(){this.destroyed=!0,!(typeof window>"u")&&(this.popstateHandler&&window.removeEventListener("popstate",this.popstateHandler),this.clickHandler&&document.removeEventListener("click",this.clickHandler,!0),this.originalPushState&&(history.pushState=this.originalPushState),this.originalReplaceState&&(history.replaceState=this.originalReplaceState))}setupAutoTracking(){this.trackScreenViews&&(this.trackScreenView(),this.observeNavigation()),(this.trackOutgoingLinks||this.trackAttributes)&&this.observeClicks()}trackScreenView(){let t=window.location.pathname+window.location.search;t!==this.lastPath&&(this.lastPath=t,this.track("screen_view",{path:window.location.pathname,origin:window.location.origin,referrer:document.referrer||void 0,referrer_name:document.referrer?this.extractDomain(document.referrer):void 0,title:document.title||void 0}))}observeNavigation(){this.popstateHandler=()=>this.trackScreenView(),window.addEventListener("popstate",this.popstateHandler),this.originalPushState=history.pushState.bind(history),this.originalReplaceState=history.replaceState.bind(history),history.pushState=(...t)=>{this.originalPushState(...t),setTimeout(()=>this.trackScreenView(),0)},history.replaceState=(...t)=>{this.originalReplaceState(...t),setTimeout(()=>this.trackScreenView(),0)}}observeClicks(){this.clickHandler=t=>{let e=t.target?.closest?.("a, [data-orbit-event]");if(e){if(this.trackOutgoingLinks&&e.tagName==="A"){let i=e.href;i&&this.isExternalLink(i)&&this.track("outgoing_link",{href:i,text:(e.textContent||"").trim().substring(0,200)})}if(this.trackAttributes){let i=e.getAttribute("data-orbit-event");if(i){let n={};for(let r of Array.from(e.attributes))if(r.name.startsWith("data-orbit-")&&r.name!=="data-orbit-event"){let s=r.name.replace("data-orbit-","");n[s]=r.value}this.track(i,n)}}}},document.addEventListener("click",this.clickHandler,!0)}async send(t){if(this.destroyed)return;this.profileId&&!t.payload.profileId&&(t.payload.profileId=this.profileId);let e=`${this.apiUrl}/api/track`;try{await fetch(e,{method:"POST",headers:{"Content-Type":"application/json","openpanel-client-id":this.clientId,"openpanel-sdk-name":c,"openpanel-sdk-version":p},body:JSON.stringify(t),keepalive:!0})}catch{}}enqueue(t){this.queue.push(t),this.flush()}async flush(){if(!this.flushing){for(this.flushing=!0;this.queue.length>0;)await this.queue.shift()();this.flushing=!1}}getPageContext(){return typeof window>"u"?{}:{path:window.location.pathname,origin:window.location.origin}}isExternalLink(t){try{return new URL(t).origin!==window.location.origin}catch{return!1}}extractDomain(t){try{return new URL(t).hostname}catch{return t}}};function h(o){return new a(o)}var d=a;export{a as ShopCircleOrbit,h as createOrbit,d as default};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["const SDK_NAME = \"shopcircle-orbit\"\nconst SDK_VERSION = \"1.0.0\"\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface OrbitOptions {\n /** Your client ID from the analytics dashboard */\n clientId: string\n /** Base URL of your analytics panel (e.g. \"https://analytics.yoursite.com\") */\n apiUrl?: string\n /** Automatically track page/screen views (default: true) */\n trackScreenViews?: boolean\n /** Automatically track clicks on outgoing links (default: false) */\n trackOutgoingLinks?: boolean\n /** Automatically track data-orbit-* attributes on clicked elements (default: false) */\n trackAttributes?: boolean\n}\n\nexport interface IdentifyTraits {\n firstName?: string\n lastName?: string\n email?: string\n avatar?: string\n [key: string]: unknown\n}\n\nexport type Properties = Record<string, unknown>\n\n// ─── SDK ──────────────────────────────────────────────────────────────────────\n\nexport class ShopCircleOrbit {\n private clientId: string\n private apiUrl: string\n private trackScreenViews: boolean\n private trackOutgoingLinks: boolean\n private trackAttributes: boolean\n private profileId: string | null = null\n private queue: Array<() => Promise<void>> = []\n private flushing = false\n private destroyed = false\n\n // Stored references for cleanup\n private popstateHandler: (() => void) | null = null\n private clickHandler: ((e: MouseEvent) => void) | null = null\n private lastPath: string | null = null\n private originalPushState: typeof history.pushState | null = null\n private originalReplaceState: typeof history.replaceState | null = null\n\n constructor(options: OrbitOptions) {\n this.clientId = options.clientId\n this.apiUrl = (options.apiUrl || \"\").replace(/\\/$/, \"\")\n this.trackScreenViews = options.trackScreenViews ?? true\n this.trackOutgoingLinks = options.trackOutgoingLinks ?? false\n this.trackAttributes = options.trackAttributes ?? false\n\n if (!this.clientId) {\n console.warn(\"[shopcircle-orbit] Missing clientId\")\n return\n }\n\n if (typeof window !== \"undefined\") {\n this.setupAutoTracking()\n }\n }\n\n // ─── Public API ───────────────────────────────────────────────────────\n\n /**\n * Track a custom event with optional properties.\n *\n * @example\n * orbit.track(\"button_clicked\", { label: \"Sign Up\", variant: \"primary\" })\n */\n track(name: string, properties?: Properties): void {\n this.enqueue(() =>\n this.send({\n type: \"track\",\n payload: {\n name,\n properties: {\n ...this.getPageContext(),\n ...properties,\n },\n },\n })\n )\n }\n\n /**\n * Identify a user. Subsequent events will be associated with this profile.\n *\n * @example\n * orbit.identify(\"user_123\", { firstName: \"John\", email: \"john@example.com\" })\n */\n identify(profileId: string, traits?: IdentifyTraits): void {\n this.profileId = profileId\n\n const { firstName, lastName, email, avatar, ...rest } = traits || {}\n\n this.enqueue(() =>\n this.send({\n type: \"identify\",\n payload: {\n profileId,\n firstName,\n lastName,\n email,\n avatar,\n properties: Object.keys(rest).length > 0 ? rest : undefined,\n },\n })\n )\n }\n\n /**\n * Reset the current user identity (e.g. on logout).\n */\n reset(): void {\n this.profileId = null\n }\n\n /**\n * Clean up event listeners. Call this when unmounting in SPA frameworks.\n */\n destroy(): void {\n this.destroyed = true\n if (typeof window === \"undefined\") return\n\n if (this.popstateHandler) {\n window.removeEventListener(\"popstate\", this.popstateHandler)\n }\n if (this.clickHandler) {\n document.removeEventListener(\"click\", this.clickHandler, true)\n }\n if (this.originalPushState) {\n history.pushState = this.originalPushState\n }\n if (this.originalReplaceState) {\n history.replaceState = this.originalReplaceState\n }\n }\n\n // ─── Auto-tracking ────────────────────────────────────────────────────\n\n private setupAutoTracking(): void {\n if (this.trackScreenViews) {\n this.trackScreenView()\n this.observeNavigation()\n }\n\n if (this.trackOutgoingLinks || this.trackAttributes) {\n this.observeClicks()\n }\n }\n\n private trackScreenView(): void {\n const path = window.location.pathname + window.location.search\n if (path === this.lastPath) return\n this.lastPath = path\n\n this.track(\"screen_view\", {\n path: window.location.pathname,\n origin: window.location.origin,\n referrer: document.referrer || undefined,\n referrer_name: document.referrer\n ? this.extractDomain(document.referrer)\n : undefined,\n title: document.title || undefined,\n })\n }\n\n private observeNavigation(): void {\n // Listen for popstate (back/forward)\n this.popstateHandler = () => this.trackScreenView()\n window.addEventListener(\"popstate\", this.popstateHandler)\n\n // Monkey-patch pushState/replaceState to detect SPA navigations\n this.originalPushState = history.pushState.bind(history)\n this.originalReplaceState = history.replaceState.bind(history)\n\n history.pushState = (...args) => {\n this.originalPushState!(...args)\n // Small delay to let the URL update\n setTimeout(() => this.trackScreenView(), 0)\n }\n\n history.replaceState = (...args) => {\n this.originalReplaceState!(...args)\n setTimeout(() => this.trackScreenView(), 0)\n }\n }\n\n private observeClicks(): void {\n this.clickHandler = (e: MouseEvent) => {\n const target = (e.target as Element)?.closest?.(\"a, [data-orbit-event]\")\n if (!target) return\n\n // Track outgoing links\n if (this.trackOutgoingLinks && target.tagName === \"A\") {\n const href = (target as HTMLAnchorElement).href\n if (href && this.isExternalLink(href)) {\n this.track(\"outgoing_link\", {\n href,\n text: (target.textContent || \"\").trim().substring(0, 200),\n })\n }\n }\n\n // Track data-orbit-* attributes\n if (this.trackAttributes) {\n const eventName = target.getAttribute(\"data-orbit-event\")\n if (eventName) {\n const props: Properties = {}\n for (const attr of Array.from(target.attributes)) {\n if (attr.name.startsWith(\"data-orbit-\") && attr.name !== \"data-orbit-event\") {\n const key = attr.name.replace(\"data-orbit-\", \"\")\n props[key] = attr.value\n }\n }\n this.track(eventName, props)\n }\n }\n }\n document.addEventListener(\"click\", this.clickHandler, true)\n }\n\n // ─── Network ──────────────────────────────────────────────────────────\n\n private async send(body: {\n type: string\n payload: Record<string, unknown>\n }): Promise<void> {\n if (this.destroyed) return\n\n // Inject profileId if set\n if (this.profileId && !body.payload.profileId) {\n body.payload.profileId = this.profileId\n }\n\n const url = `${this.apiUrl}/api/track`\n\n try {\n await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"openpanel-client-id\": this.clientId,\n \"openpanel-sdk-name\": SDK_NAME,\n \"openpanel-sdk-version\": SDK_VERSION,\n },\n body: JSON.stringify(body),\n keepalive: true,\n })\n } catch {\n // Silently fail - analytics should never break the app\n }\n }\n\n // ─── Queue ────────────────────────────────────────────────────────────\n\n private enqueue(fn: () => Promise<void>): void {\n this.queue.push(fn)\n this.flush()\n }\n\n private async flush(): Promise<void> {\n if (this.flushing) return\n this.flushing = true\n\n while (this.queue.length > 0) {\n const fn = this.queue.shift()!\n await fn()\n }\n\n this.flushing = false\n }\n\n // ─── Helpers ──────────────────────────────────────────────────────────\n\n private getPageContext(): Properties {\n if (typeof window === \"undefined\") return {}\n return {\n path: window.location.pathname,\n origin: window.location.origin,\n }\n }\n\n private isExternalLink(href: string): boolean {\n try {\n return new URL(href).origin !== window.location.origin\n } catch {\n return false\n }\n }\n\n private extractDomain(url: string): string {\n try {\n return new URL(url).hostname\n } catch {\n return url\n }\n }\n}\n\n// ─── Convenience factory ──────────────────────────────────────────────────────\n\n/**\n * Create a new ShopCircleOrbit instance.\n *\n * @example\n * import { createOrbit } from \"shopcircle-orbit\"\n *\n * const orbit = createOrbit({\n * clientId: \"your-client-id\",\n * apiUrl: \"https://analytics.yoursite.com\",\n * })\n *\n * orbit.track(\"purchase\", { amount: 99.99 })\n */\nexport function createOrbit(options: OrbitOptions): ShopCircleOrbit {\n return new ShopCircleOrbit(options)\n}\n\n// Default export for convenience\nexport default ShopCircleOrbit\n"],"mappings":"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","names":["SDK_NAME","SDK_VERSION","ShopCircleOrbit","options","name","properties","profileId","traits","firstName","lastName","email","avatar","rest","path","args","e","target","href","eventName","props","attr","key","body","url","fn","createOrbit","index_default"]}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "shopcircle-orbit",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Lightweight analytics SDK for ShopCircle Orbit. Track events, identify users, and measure engagement.",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "sideEffects": false,
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsup",
27
+ "dev": "tsup --watch",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "keywords": [
31
+ "analytics",
32
+ "tracking",
33
+ "events",
34
+ "shopcircle",
35
+ "orbit"
36
+ ],
37
+ "author": "ShopCircle",
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/shopcircle/orbit-sdk"
42
+ },
43
+ "homepage": "https://github.com/shopcircle/orbit-sdk#readme",
44
+ "bugs": {
45
+ "url": "https://github.com/shopcircle/orbit-sdk/issues"
46
+ },
47
+ "devDependencies": {
48
+ "tsup": "^8.0.0",
49
+ "typescript": "^5.0.0"
50
+ }
51
+ }