@sightspool/sdk 0.1.0 → 0.1.1
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 +139 -1
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -14,6 +14,10 @@ them).
|
|
|
14
14
|
> **not** act on your surface (surveys/nudges/experiments are Wave 0005, and every one
|
|
15
15
|
> is human-gated). Trigger sensitivity and intent inference calibrate with live traffic.
|
|
16
16
|
|
|
17
|
+
**Docs:** [full reference + CSP & framework guides](https://sightspool.github.io/sdk/) ·
|
|
18
|
+
[llms.txt](https://sightspool.github.io/sdk/llms.txt) (the machine-readable install/CSP/config
|
|
19
|
+
doc for agents) · [npm](https://www.npmjs.com/package/@sightspool/sdk)
|
|
20
|
+
|
|
17
21
|
---
|
|
18
22
|
|
|
19
23
|
## Install — two lines
|
|
@@ -83,7 +87,7 @@ The script tag also reads these optional attributes (the no-build equivalent of
|
|
|
83
87
|
|
|
84
88
|
| option | type | default | purpose |
|
|
85
89
|
|---|---|---|---|
|
|
86
|
-
| `key` | `string` | — | **required.** Your publishable key (`pk_live_…`), from the Connections → In-product SDK card. Publishable — safe to ship in client JS. |
|
|
90
|
+
| `key` | `string` | — | **required.** Your publishable key (`pk_test_…` / `pk_live_…`), from the Connections → In-product SDK card. Publishable — safe to ship in client JS. See [Keys & environments](#keys--environments). |
|
|
87
91
|
| `endpoint` | `string` | the bundle's origin (script tag) / `https://app.sightspool.com` (npm) | Ingest base URL. The `<script>` install auto-resolves it to wherever `sdk.global.js` was served from (your app), so the key alone is enough; override for a CDN-hosted bundle or dev. |
|
|
88
92
|
| `boundaryAsk` | `boolean` | `true` | Show the one-tap "did you do what you came to do?" ask at session boundaries. |
|
|
89
93
|
| `consent` | `boolean` | `true` | Start capturing immediately. Set `false` to stay paused until you call `Sightspool.consent(true)` (or `start()`) after obtaining consent. |
|
|
@@ -107,6 +111,140 @@ un-allowlisted origin.
|
|
|
107
111
|
|
|
108
112
|
---
|
|
109
113
|
|
|
114
|
+
## Keys & environments
|
|
115
|
+
|
|
116
|
+
Your key is **publishable** — safe to ship in client JS (the Stripe `pk_` model). Two
|
|
117
|
+
prefixes, one per environment:
|
|
118
|
+
|
|
119
|
+
| prefix | use it for |
|
|
120
|
+
|---|---|
|
|
121
|
+
| `pk_test_…` | development / staging / preview deploys |
|
|
122
|
+
| `pk_live_…` | production |
|
|
123
|
+
|
|
124
|
+
The SDK treats both prefixes **identically** — there's no client-side special-casing; the
|
|
125
|
+
prefix tells *Sightspool* (at ingest) which environment a Signal belongs to, so test traffic
|
|
126
|
+
never mixes into production analytics. Issue both from **Connections → In-product SDK**.
|
|
127
|
+
|
|
128
|
+
> The SDK also **no-ops on localhost** by default (see `captureOnLocalhost`), so even a
|
|
129
|
+
> `pk_live_` key won't capture from `npm run dev`. Test keys are for *deployed* non-prod
|
|
130
|
+
> environments (staging, previews).
|
|
131
|
+
|
|
132
|
+
Keep the key in an environment variable rather than hardcoding it, and pick test vs live by
|
|
133
|
+
environment. The key is exposed to the browser, so use your framework's **client** env-var
|
|
134
|
+
prefix (`NEXT_PUBLIC_`, `VITE_`, `PUBLIC_`, …) — it's publishable, so that's expected:
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
Sightspool.init({ key: process.env.NEXT_PUBLIC_SIGHTSPOOL_KEY })
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# .env.development / preview
|
|
142
|
+
NEXT_PUBLIC_SIGHTSPOOL_KEY=pk_test_…
|
|
143
|
+
# .env.production
|
|
144
|
+
NEXT_PUBLIC_SIGHTSPOOL_KEY=pk_live_…
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Framework integration
|
|
150
|
+
|
|
151
|
+
### Next.js (App Router) — `next/script`
|
|
152
|
+
|
|
153
|
+
The idiomatic install is `next/script`, not a raw `<script>`. Add it once in your root
|
|
154
|
+
layout — the tag auto-`init`s from `data-sightspool-key`:
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
// app/layout.tsx
|
|
158
|
+
import Script from 'next/script'
|
|
159
|
+
|
|
160
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
161
|
+
return (
|
|
162
|
+
<html lang="en">
|
|
163
|
+
<body>
|
|
164
|
+
{children}
|
|
165
|
+
<Script
|
|
166
|
+
src="https://app.sightspool.com/sdk.global.js"
|
|
167
|
+
data-sightspool-key={process.env.NEXT_PUBLIC_SIGHTSPOOL_KEY}
|
|
168
|
+
strategy="afterInteractive"
|
|
169
|
+
/>
|
|
170
|
+
</body>
|
|
171
|
+
</html>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Then `identify` the user once known (e.g. a client component after auth):
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
'use client'
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
window.Sightspool?.identify(user.id, { account: user.account, plan: user.plan })
|
|
182
|
+
}, [user])
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
> `data-sightspool-key` is inlined at build time, so `NEXT_PUBLIC_SIGHTSPOOL_KEY` must be set
|
|
186
|
+
> in the environment Next builds in. `strategy="afterInteractive"` keeps it off the critical
|
|
187
|
+
> path.
|
|
188
|
+
|
|
189
|
+
### React (bundler install)
|
|
190
|
+
|
|
191
|
+
Install the package and call `init` once at app start (a top-level effect or your entry
|
|
192
|
+
module):
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import { useEffect } from 'react'
|
|
196
|
+
import Sightspool from '@sightspool/sdk'
|
|
197
|
+
|
|
198
|
+
export function SightspoolBoot({ userId, account, plan }) {
|
|
199
|
+
useEffect(() => {
|
|
200
|
+
Sightspool.init({ key: import.meta.env.VITE_SIGHTSPOOL_KEY })
|
|
201
|
+
}, [])
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
if (userId) Sightspool.identify(userId, { account, plan })
|
|
204
|
+
}, [userId, account, plan])
|
|
205
|
+
return null
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
> A first-class **`@sightspool/react`** wrapper (a `<SightspoolProvider>` + a `useSightspool`
|
|
210
|
+
> hook over `init`/`identify`) is planned —
|
|
211
|
+
> [issue #3](https://github.com/sightspool/sdk/issues/3).
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Content-Security-Policy
|
|
216
|
+
|
|
217
|
+
If your app sets a CSP, allow the SDK's two footprints — the **script load** and the
|
|
218
|
+
**ingest beacon**. With the standard install they're the *same host* (the bundle is served
|
|
219
|
+
from the app it ingests to), so it's one host in two directives:
|
|
220
|
+
|
|
221
|
+
**Script-tag install**
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
script-src https://app.sightspool.com;
|
|
225
|
+
connect-src https://app.sightspool.com;
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**npm / bundler install** — the SDK is bundled into your own first-party JS, so no
|
|
229
|
+
`script-src` host is needed; only the ingest origin:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
connect-src https://app.sightspool.com;
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
If you pass a custom `endpoint`, use *that* origin in `connect-src`. The beacon goes via
|
|
236
|
+
`navigator.sendBeacon` with a `fetch(keepalive)` fallback — both governed by `connect-src`.
|
|
237
|
+
|
|
238
|
+
- **`strict-dynamic` / nonce.** Under `script-src 'strict-dynamic'`, host allowlists are
|
|
239
|
+
ignored for scripts — give the `<script>` tag your per-request nonce (`nonce={nonce}` in
|
|
240
|
+
Next) so it's trusted. `connect-src` still needs the ingest host.
|
|
241
|
+
- **Prompt styles.** The one-tap prompt renders into a **shadow root** and injects its own
|
|
242
|
+
`<style>`. Under a strict `style-src` without `'unsafe-inline'`, those styles may not apply
|
|
243
|
+
— the prompt stays **fully functional but unstyled** (the SDK never throws into your page).
|
|
244
|
+
Add `'unsafe-inline'` to `style-src` if you want it styled.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
110
248
|
## What it captures
|
|
111
249
|
|
|
112
250
|
- **Passively, no wiring** — route/screen sequence, clicks, **dead-clicks** and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sightspool/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Sightspool in-product capture SDK — captures user intent, effort, and account at the moment of friction.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -43,17 +43,19 @@
|
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=18"
|
|
45
45
|
},
|
|
46
|
+
"packageManager": "pnpm@9.15.0",
|
|
46
47
|
"publishConfig": {
|
|
47
48
|
"access": "public"
|
|
48
49
|
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup",
|
|
52
|
+
"type-check": "tsc --noEmit",
|
|
53
|
+
"test": "node --test __tests__/*.test.ts",
|
|
54
|
+
"prepublishOnly": "pnpm run build"
|
|
55
|
+
},
|
|
49
56
|
"devDependencies": {
|
|
50
57
|
"@types/node": "^24.10.4",
|
|
51
58
|
"tsup": "^8.5.0",
|
|
52
59
|
"typescript": "^5.9.3"
|
|
53
|
-
},
|
|
54
|
-
"scripts": {
|
|
55
|
-
"build": "tsup",
|
|
56
|
-
"type-check": "tsc --noEmit",
|
|
57
|
-
"test": "node --test __tests__/*.test.ts"
|
|
58
60
|
}
|
|
59
|
-
}
|
|
61
|
+
}
|