{"_id":"@aflaj/sdk-browser","_rev":"2-48857cdad9da4698d21d6cff099b1b83","name":"@aflaj/sdk-browser","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@aflaj/sdk-browser","version":"0.1.0","keywords":["analytics","autocapture","browser","aflaj"],"license":"MIT","_id":"@aflaj/sdk-browser@0.1.0","maintainers":[{"name":"huiyu","email":"huiyu219@gmail.com"}],"homepage":"https://github.com/knotmark-ai/aflaj#readme","bugs":{"url":"https://github.com/knotmark-ai/aflaj/issues"},"dist":{"shasum":"a62a1524c32677e804da7c82bac7816d2102b694","tarball":"https://registry.npmjs.org/@aflaj/sdk-browser/-/sdk-browser-0.1.0.tgz","fileCount":25,"integrity":"sha512-YONBKl/SXal3hX8+fP+wnVuBplAlZnt+i1U+U5THwBxbSbLQP0G0w1JYtGg6ZjXxM6tP3fGnz3eC+VYMnEdZ+w==","signatures":[{"sig":"MEQCIGaJaQTMA8gABY6Gq/KCEXAMGmFPjHJWcKvJcZhJg3/wAiAxTmnwyg6JMB53bO2UyRKPm9PVcuusv7/PkNMQJIcRgA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":382083},"main":"./dist/index.js","type":"module","types":"./dist/types/index.d.ts","unpkg":"./dist/aflaj.min.js","module":"./dist/index.js","exports":{".":{"types":"./dist/types/index.d.ts","default":"./dist/index.js"},"./script":"./dist/aflaj.min.js","./package.json":"./package.json"},"gitHead":"ad0b6bfd93b44d56d17de45e2cdcaa92ac5649f6","scripts":{"build":"node build.ts","prepack":"npm run build","typecheck":"tsc --noEmit"},"_npmUser":{"name":"huiyu","email":"huiyu219@gmail.com"},"jsdelivr":"./dist/aflaj.min.js","repository":{"url":"git+https://github.com/knotmark-ai/aflaj.git","type":"git","directory":"connectors/sdk-browser"},"_npmVersion":"10.9.8","description":"The aflaj browser collector: pageviews, clicks, forms, media milestones and page-structure snapshots. Zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.0","browserslist":["chrome >= 80","edge >= 80","firefox >= 74","safari >= 13.1","ios_saf >= 13.4","opera >= 67","samsung >= 13"],"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rolldown":"^1.2.1","happy-dom":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk-browser_0.1.0_1785633857236_0.23273499506995776","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@aflaj/sdk-browser","version":"0.1.1","license":"MIT","description":"The aflaj browser collector: pageviews, clicks, forms, media milestones and page-structure snapshots. Zero runtime dependencies.","type":"module","sideEffects":false,"main":"./dist/index.js","module":"./dist/index.js","types":"./dist/types/index.d.ts","unpkg":"./dist/aflaj.min.js","jsdelivr":"./dist/aflaj.min.js","exports":{".":{"types":"./dist/types/index.d.ts","default":"./dist/index.js"},"./script":"./dist/aflaj.min.js","./package.json":"./package.json"},"browserslist":["chrome >= 80","edge >= 80","firefox >= 74","safari >= 13.1","ios_saf >= 13.4","opera >= 67","samsung >= 13"],"publishConfig":{"access":"public"},"keywords":["analytics","autocapture","browser","aflaj"],"scripts":{"build":"node build.ts","prepack":"npm run build","typecheck":"tsc --noEmit"},"devDependencies":{"happy-dom":"^20.0.0","rolldown":"^1.2.1"},"homepage":"https://aflaj.knotmark.com","bugs":{"email":"info@knotmark.com"},"_id":"@aflaj/sdk-browser@0.1.1","gitHead":"394ab242afe5a5942b48a5f59f454063e8a8f885","_nodeVersion":"22.23.0","_npmVersion":"10.9.8","dist":{"integrity":"sha512-yV58SQWP3DQYeExoPDqWD/vgsRT7BCMler6gb3nSagPhMhND6AJL3EZDM7I9k6bgF3TOoi4bBB7PElrmXz7Zvw==","shasum":"1f92be1eeafdaaefdc1a41e8f4b6e37f436079e1","tarball":"https://registry.npmjs.org/@aflaj/sdk-browser/-/sdk-browser-0.1.1.tgz","fileCount":25,"unpackedSize":382017,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDvUlQa12yxSGkMMDyj4afuCBHUd5RMQpMatatn9MGvhwIgbpiJeBe3gYxs7p4bzDiX3jqgEDjcbY3bZXN3jDAK8Mw="}]},"_npmUser":{"name":"huiyu","email":"huiyu219@gmail.com"},"directories":{},"maintainers":[{"name":"huiyu","email":"huiyu219@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk-browser_0.1.1_1785648077895_0.747754003581113"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-02T01:24:17.060Z","modified":"2026-08-02T05:21:18.212Z","0.1.0":"2026-08-02T01:24:17.389Z","0.1.1":"2026-08-02T05:21:18.028Z"},"bugs":{"email":"info@knotmark.com"},"license":"MIT","homepage":"https://aflaj.knotmark.com","keywords":["analytics","autocapture","browser","aflaj"],"description":"The aflaj browser collector: pageviews, clicks, forms, media milestones and page-structure snapshots. Zero runtime dependencies.","maintainers":[{"name":"huiyu","email":"huiyu219@gmail.com"}],"readme":"# @aflaj/sdk-browser\n\nBrowser event collection for [Aflaj](https://aflaj.knotmark.com) — product analytics that\ndoes not ask you to instrument anything first.\n\nDrop it in, and it records what visitors do. Which of those events *mean* something —\n\"this is the signup button\", \"this is activation\" — is decided later, against data you have\nalready collected, and can be changed without losing history.\n\n```\n7.8 KB gzipped  ·  zero runtime dependencies  ·  ES2020\n```\n\n---\n\n## ⚠️ Preview\n\n**This is a preview release. The product is in demo/trial stage and this package's API is\nnot stable yet.**\n\n- Breaking changes may land in any `0.x` release. **Pin an exact version.**\n- The collector endpoint is not a general-purpose public service yet; you need a project.\n- Nothing here is load-bearing for anyone's production analytics today.\n\nIf you are evaluating it, that is exactly the intended use. If you are about to depend on\nit, talk to us first: <info@knotmark.com>.\n\n---\n\n## Install\n\n```bash\nnpm install @aflaj/sdk-browser\n```\n\n```ts\nimport { install } from \"@aflaj/sdk-browser\";\n\ninstall({\n  key: \"pk_live_…\",                       // public write key — safe in a browser\n  endpoint: \"https://aflaj.knotmark.com\", // where events go\n  window,                                 // the window to attach to\n});\n```\n\nOr as a script tag, via any npm CDN:\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/@aflaj/sdk-browser@0.1.1/dist/aflaj.min.js\"></script>\n<script>\n  AflajSDK.install({ key: \"pk_live_…\", endpoint: \"https://aflaj.knotmark.com\", window });\n</script>\n```\n\n> `window` is a parameter rather than a global lookup, so the SDK also runs where the host\n> owns the window — a WebView shell, an SSR boundary, a test.\n\n### API\n\n```ts\nconst aflaj = install({ key, endpoint, window });\n\naflaj.track(\"plan_upgraded\", { plan: \"pro\" }); // your own event\naflaj.identify(\"user_8123\");                   // name the visitor\nawait aflaj.flush();                           // send what is buffered\naflaj.shutdown();                              // detach, and restore what was patched\n```\n\n`install()` is idempotent — calling it twice on one page gives you the same instance back,\nnot two collectors.\n\n<details>\n<summary>Other options</summary>\n\n| | Default | |\n|---|---|---|\n| `autocapture` | `true` | click / submit / change / media capture |\n| `snapshots` | `true` | page structure summaries |\n| `batchMax` | `100` | events per request |\n| `flushIntervalMs` | `5000` | how often a partial batch goes out |\n| `maxBuffered` | — | buffer ceiling; the oldest events are dropped first |\n| `onError` | — | called with anything the SDK swallowed |\n\n`transport`, `now`, `timers`, `random`, `entropy` and `backoff` are injectable for testing.\n\n</details>\n\n---\n\n## What it collects\n\n**Automatically:** page views (including SPA route changes) · clicks, with the element's\nstructural context · form submissions, as field names and types · `select` / radio /\ncheckbox selections · native `<video>` / `<audio>` milestones · a structural summary of\neach page.\n\n**Identity:** an anonymous id, minted locally and persisted. `identify()` adds your own\nuser id to subsequent events and **keeps the same anonymous id**, so the session before\nsign-in can be joined to the one after.\n\n**Nothing is named in advance.** Clicks are recorded with the element's tag, visible text,\npath and `data-*` attributes — never a hardcoded selector. Which one is the signup button\nis a decision made later, and changing that decision does not require re-collecting\nanything.\n\n## What it will not collect\n\nThese are structural, not settings — there is no flag that turns them on.\n\n| | |\n|---|---|\n| **Credentials** | It reads exactly one storage key: its own anonymous id. Not your session tokens, not your cookies, not anyone else's keys. |\n| **Password / email / tel / card fields** | Nothing at all — not even whether they were filled. |\n| **What a visitor typed** | Free-text and `textarea` content, including `contenteditable`, never enters memory. Only what the page's *author* wrote — option values, button labels, field names. |\n| **URL secrets** | The fragment is dropped whole (OAuth tokens live there) and query strings are reduced to known marketing parameters (reset tokens and magic links live there). |\n| **Your page** | It writes only under its own storage prefix, injects no third-party script, sets no third-party cookie, and `shutdown()` restores every patched global. |\n\nInternal errors are swallowed rather than raised. **Breaking the host page is the one\nfailure this package treats as unforgivable.**\n\n### Page snapshots\n\nSnapshots exist so that a redesign can be detected and metric definitions re-aligned to it.\nSo the question they answer is *\"did this page's structure change\"* — and the test for what\nbelongs in one is **\"is it the same across two refreshes\"**, not \"is it visible\".\n\nClass names, inline styles, script tags, base64 images and generated ids are stripped at\ncapture time. Text is not carried. Link hrefs keep their first path segment only, so\n`/u/alice` and `/u/bob` are one route. Repeated identical siblings collapse to a shape plus\na coarse count.\n\nThe trade is stated rather than hidden: **rewording a heading is no longer detected**, and\nneither is a list growing within one count bucket. Structure — new fields, new sections, new\nroutes, a new pricing tier — still is.\n\n---\n\n## Sizes and support\n\n| | Raw | gzip |\n|---|---|---|\n| `dist/index.js` (ESM) | 20.5 KB | **7.8 KB** |\n| `dist/aflaj.min.js` (IIFE) | 20.5 KB | **7.9 KB** |\n\nBoth are asserted in CI against a budget, so growth is a failing build rather than a\nsurprise.\n\n**Baseline: ES2020** — Chrome 80 · Edge 80 · Firefox 74 · Safari 13.1 (iOS 13.4) · Opera 67\n· Samsung Internet 13.\n\nOnly `JSON`, `Promise`, `querySelectorAll` and `addEventListener` are required. Everything\nelse degrades rather than fails: without `fetch` only the unload beacon sends; without\n`localStorage` the anonymous id lives for the session; without `history.pushState` SPA route\nchanges are not recorded. Below the baseline the browser refuses the script outright and\nnothing runs — the host page is unaffected.\n\n---\n\n## Licence\n\n[MIT](LICENSE) — it has to be embeddable to be useful.\n","readmeFilename":"README.md"}