{"_id":"@aient/otel-browser","_rev":"6-62768ae47a6207acb48d673ab9af160a","name":"@aient/otel-browser","dist-tags":{"latest":"0.6.0"},"versions":{"0.3.0":{"name":"@aient/otel-browser","version":"0.3.0","author":{"name":"Triple Alpha AB"},"license":"MIT","_id":"@aient/otel-browser@0.3.0","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"dist":{"shasum":"f3baf3961d9f76fadb1f1557874a384770746379","tarball":"https://registry.npmjs.org/@aient/otel-browser/-/otel-browser-0.3.0.tgz","fileCount":17,"integrity":"sha512-FMaU4I9ZYhvOB4zxqasg+0H43umTFz+JxbYe7GDJe5/yJgVUjISxregeT4fr2Qtr1UwA4+TyTpJV19BopxjLlQ==","signatures":[{"sig":"MEQCIEWINSJ4C6E5DcZ98OUaCjp+5tUB+CZxbof5oA9llyvOAiAsiN4gRkUtdOJ8ptJO6mVbIersEhs7yNpwS/Bpd6oI9g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1166951},"type":"module","_from":"file:aient-otel-browser-0.3.0.tgz","types":"./dist/types/index.d.ts","engines":{"node":">=18.19.0"},"exports":{".":{"types":"./dist/types/index.d.ts","default":"./dist/index.js"},"./cdn":{"default":"./dist/cdn/index.js"}},"private":false,"scripts":{"lint":"true","size":"node -e \"const fs=require('fs');const zlib=require('zlib');const b=fs.readFileSync('dist/cdn/index.js');const gz=zlib.gzipSync(b,{level:9});const kb=(gz.length/1024).toFixed(1);const max=200;console.log('cdn gz',kb+'kb');if(gz.length>max*1024){console.error('Size limit exceeded:'+kb+'kb > '+max+'kb');process.exit(1)}\"","build":"node ./build.mjs","clean":"rm -rf dist .dist-tmp .dist-backup","lint:fix":"true","test:unit":"pnpm unit-test","unit-test":"vitest --run","type-check":"tsc --noEmit","test:unit:watch":"pnpm unit-test-watch","unit-test-watch":"vitest"},"_npmUser":{"name":"haf","email":"henrik@haf.se"},"_resolved":"/private/var/folders/ln/9kcrdg0x1_s2w5m05flp9v280000gn/T/1abc6554a23d1d31c0171a206d7262ee/aient-otel-browser-0.3.0.tgz","_integrity":"sha512-FMaU4I9ZYhvOB4zxqasg+0H43umTFz+JxbYe7GDJe5/yJgVUjISxregeT4fr2Qtr1UwA4+TyTpJV19BopxjLlQ==","_npmVersion":"11.8.0","description":"Minimal browser-only OpenTelemetry bootstrap for Aient","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","dependencies":{"protobufjs":"^7.5.4","@opentelemetry/core":"^2.2.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/context-zone":"^2.2.0","@opentelemetry/sdk-trace-web":"^2.2.0","@opentelemetry/sdk-trace-base":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/otlp-transformer":"^0.208.0","@opentelemetry/otlp-exporter-base":"^0.208.0","@opentelemetry/instrumentation-fetch":"^0.208.0","@opentelemetry/instrumentation-document-load":"^0.54.0","@opentelemetry/instrumentation-user-interaction":"^0.53.0","@opentelemetry/instrumentation-xml-http-request":"^0.208.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^27.3.0","vitest":"4.0.15","esbuild":"^0.27.1","typescript":"^5.9.3","@types/node":"25.0.1","typescript-config":"1.0.0"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0"},"_npmOperationalInternal":{"tmp":"tmp/otel-browser_0.3.0_1775196862172_0.802190893044944","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@aient/otel-browser","version":"0.4.0","author":{"name":"Triple Alpha AB"},"license":"MIT","_id":"@aient/otel-browser@0.4.0","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"dist":{"shasum":"4ae98267a8142e4a26636cc815747546412eaf7c","tarball":"https://registry.npmjs.org/@aient/otel-browser/-/otel-browser-0.4.0.tgz","fileCount":17,"integrity":"sha512-+aFdXdW7uWM+0xnQMG1ilcs+Z09gZTRzjGyueT5DILnDut8xuwGGSOxvthw4te0rKqLkA5zQDQMe2IqC/n0GeA==","signatures":[{"sig":"MEUCIQCSj0XNE3rhrQaQsWYqOKagu0xw83dF6KyU0BDYevMkgAIgNnIcs+dyoS8NCzC1XUkv3JNfzQsRxDyNlj/EXc9g1r0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2413053},"type":"module","types":"./dist/types/index.d.ts","engines":{"node":">=18.19.0"},"exports":{".":{"types":"./dist/types/index.d.ts","default":"./dist/index.js"},"./cdn":{"default":"./dist/cdn/index.js"}},"gitHead":"8c9197371c7a2312ed3a19c1649761e7c9019365","private":false,"scripts":{"lint":"true","size":"node -e \"const fs=require('fs');const zlib=require('zlib');const b=fs.readFileSync('dist/cdn/index.js');const gz=zlib.gzipSync(b,{level:9});const kb=(gz.length/1024).toFixed(1);const max=200;console.log('cdn gz',kb+'kb');if(gz.length>max*1024){console.error('Size limit exceeded:'+kb+'kb > '+max+'kb');process.exit(1)}\"","test":"pnpm test:unit","build":"node ./build.mjs","clean":"rm -rf dist .dist-tmp .dist-backup .build-lock","prepare":"pnpm build","lint:fix":"true","test:unit":"pnpm unit-test","unit-test":"vitest --run","type-check":"tsc --noEmit","test:unit:watch":"pnpm unit-test-watch","unit-test-watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:1a4cef7d-abdd-4db2-918f-d8bfb39ca0cb"}},"_npmVersion":"11.11.0","description":"Minimal browser-only OpenTelemetry bootstrap for Aient","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","dependencies":{"@opentelemetry/core":"^2.2.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/context-zone":"^2.2.0","@opentelemetry/sdk-trace-web":"^2.2.0","@opentelemetry/sdk-trace-base":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/instrumentation-fetch":"^0.208.0","@opentelemetry/instrumentation-document-load":"^0.54.0","@opentelemetry/instrumentation-user-interaction":"^0.53.0","@opentelemetry/instrumentation-xml-http-request":"^0.208.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^27.3.0","vitest":"4.0.15","esbuild":"^0.27.1","typescript":"^5.9.3","@types/node":"25.0.1","typescript-config":"workspace:*"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0"},"_npmOperationalInternal":{"tmp":"tmp/otel-browser_0.4.0_1778167718035_0.029361789502901692","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@aient/otel-browser","version":"0.4.1","author":{"name":"Triple Alpha AB"},"license":"MIT","_id":"@aient/otel-browser@0.4.1","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"dist":{"shasum":"e80529ae27f99b6892e11fc5499435399c35560d","tarball":"https://registry.npmjs.org/@aient/otel-browser/-/otel-browser-0.4.1.tgz","fileCount":17,"integrity":"sha512-vA+vz7sxO3PBOL0N5vIYbECp1RYkMJLHEREAXl6GNHYQeyAM2nPgJ1zOQzvH1oaMOyURxDZGuyuvWrecrZQWAg==","signatures":[{"sig":"MEYCIQD0MWcvhie0CYwTUcpSgY88o6E0CPBJB+FRDDHWpa1/uAIhAI2uB1WhfN+jHQHI9u6k38fWDAqmGzgHQ8FbJn+EpIl+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2418571},"type":"module","types":"./dist/types/index.d.ts","engines":{"node":">=18.19.0"},"exports":{".":{"types":"./dist/types/index.d.ts","default":"./dist/index.js"},"./cdn":{"default":"./dist/cdn/index.js"}},"gitHead":"44a613b78fb59fdedb0f626ab6c438982c50be54","private":false,"scripts":{"lint":"true","size":"node -e \"const fs=require('fs');const zlib=require('zlib');const b=fs.readFileSync('dist/cdn/index.js');const gz=zlib.gzipSync(b,{level:9});const kb=(gz.length/1024).toFixed(1);const max=200;console.log('cdn gz',kb+'kb');if(gz.length>max*1024){console.error('Size limit exceeded:'+kb+'kb > '+max+'kb');process.exit(1)}\"","test":"pnpm test:unit","build":"node ./build.mjs","clean":"rm -rf dist .dist-tmp .dist-backup .build-lock","prepare":"pnpm build","lint:fix":"true","test:unit":"pnpm unit-test","unit-test":"vitest --run","type-check":"tsc --noEmit","test:unit:watch":"pnpm unit-test-watch","unit-test-watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:1a4cef7d-abdd-4db2-918f-d8bfb39ca0cb"}},"_npmVersion":"11.13.0","description":"Minimal browser-only OpenTelemetry bootstrap for Aient","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","dependencies":{"@opentelemetry/core":"^2.2.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/context-zone":"^2.2.0","@opentelemetry/sdk-trace-web":"^2.2.0","@opentelemetry/sdk-trace-base":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/instrumentation-fetch":"^0.208.0","@opentelemetry/instrumentation-document-load":"^0.54.0","@opentelemetry/instrumentation-user-interaction":"^0.53.0","@opentelemetry/instrumentation-xml-http-request":"^0.208.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^27.3.0","vitest":"4.0.15","esbuild":"^0.27.1","typescript":"^5.9.3","@types/node":"25.0.1","typescript-config":"workspace:*"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0"},"_npmOperationalInternal":{"tmp":"tmp/otel-browser_0.4.1_1780936707085_0.7011615963991888","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@aient/otel-browser","version":"0.5.0","author":{"name":"Triple Alpha AB"},"license":"MIT","_id":"@aient/otel-browser@0.5.0","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"dist":{"shasum":"f93079813009a43c3c06060fdefdd7c1bf487de6","tarball":"https://registry.npmjs.org/@aient/otel-browser/-/otel-browser-0.5.0.tgz","fileCount":18,"integrity":"sha512-AplO4zGLB/QuBq6u/C0+tK51lSfFOS95hbWDR+ve7OnDvaoCjuzSk5uOpcmlTvBtzU/iYLSCA4fC4CcgVGLo+g==","signatures":[{"sig":"MEYCIQD0nAbe4uItDZ97+XPNU9c5ajK211lqGYInRrIbrPjc+wIhAOuJ44WBoZCKXgpYBtsUm7PY7NQZIkJ2pO6JdYLibal8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2443176},"type":"module","types":"./dist/types/index.d.ts","engines":{"node":">=18.19.0"},"exports":{".":{"types":"./dist/types/index.d.ts","default":"./dist/index.js"},"./cdn":{"default":"./dist/cdn/index.js"}},"gitHead":"40762c5656e189aeac15c3d28d2cf4af4552231a","private":false,"scripts":{"lint":"true","size":"node -e \"const fs=require('fs');const zlib=require('zlib');const b=fs.readFileSync('dist/cdn/index.js');const gz=zlib.gzipSync(b,{level:9});const kb=(gz.length/1024).toFixed(1);const max=200;console.log('cdn gz',kb+'kb');if(gz.length>max*1024){console.error('Size limit exceeded:'+kb+'kb > '+max+'kb');process.exit(1)}\"","test":"pnpm test:unit","build":"node ./build.mjs","clean":"rm -rf dist .dist-tmp .dist-backup .build-lock","prepare":"pnpm build","lint:fix":"true","test:unit":"pnpm unit-test","unit-test":"vitest --run","type-check":"tsc --noEmit","test:unit:watch":"pnpm unit-test-watch","unit-test-watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:1a4cef7d-abdd-4db2-918f-d8bfb39ca0cb"}},"_npmVersion":"11.16.0","description":"Minimal browser-only OpenTelemetry bootstrap for Aient","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"@opentelemetry/core":"^2.2.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/context-zone":"^2.2.0","@opentelemetry/sdk-trace-web":"^2.2.0","@opentelemetry/sdk-trace-base":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/instrumentation-fetch":"^0.208.0","@opentelemetry/instrumentation-document-load":"^0.54.0","@opentelemetry/instrumentation-user-interaction":"^0.53.0","@opentelemetry/instrumentation-xml-http-request":"^0.208.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^27.3.0","vitest":"4.0.15","esbuild":"^0.27.1","typescript":"^5.9.3","@types/node":"25.0.1","typescript-config":"workspace:*"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0"},"_npmOperationalInternal":{"tmp":"tmp/otel-browser_0.5.0_1784564361351_0.18310932619843334","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"@aient/otel-browser","version":"0.5.1","author":{"name":"Triple Alpha AB"},"license":"MIT","_id":"@aient/otel-browser@0.5.1","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"dist":{"shasum":"7517514a7a79807575a839ccf0321dc488b25e25","tarball":"https://registry.npmjs.org/@aient/otel-browser/-/otel-browser-0.5.1.tgz","fileCount":18,"integrity":"sha512-EV+Klwx4De6khPMDQx5fc3iRaN+bE67ZF2rKJvcydzSXUzBlckOU4UVv6LkHgHcvuDdku1CuJkShryS+jVyWhg==","signatures":[{"sig":"MEYCIQCv+pjw4SvuANbGbS1Z/duSNE6Hl0jhUH/VObMJkWIOhAIhAOhtogCRMNQZgHebA1aFWRnmLBHaKPg3wL9PPisYiAaW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2483507},"type":"module","types":"./dist/types/index.d.ts","engines":{"node":">=18.19.0"},"exports":{".":{"types":"./dist/types/index.d.ts","default":"./dist/index.js"},"./cdn":{"default":"./dist/cdn/index.js"}},"gitHead":"8bcc0056058fade3fcd83d0aca6ce1d649dab75a","private":false,"scripts":{"lint":"true","size":"node -e \"const fs=require('fs');const zlib=require('zlib');const b=fs.readFileSync('dist/cdn/index.js');const gz=zlib.gzipSync(b,{level:9});const kb=(gz.length/1024).toFixed(1);const max=200;console.log('cdn gz',kb+'kb');if(gz.length>max*1024){console.error('Size limit exceeded:'+kb+'kb > '+max+'kb');process.exit(1)}\"","test":"pnpm test:unit","build":"node ./build.mjs","clean":"rm -rf dist .dist-tmp .dist-backup .build-lock","prepare":"pnpm build","lint:fix":"true","test:unit":"pnpm unit-test","unit-test":"vitest --run","type-check":"tsc --noEmit","test:unit:watch":"pnpm unit-test-watch","unit-test-watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:1a4cef7d-abdd-4db2-918f-d8bfb39ca0cb"}},"_npmVersion":"11.16.0","description":"Minimal browser-only OpenTelemetry bootstrap for Aient","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"@opentelemetry/core":"^2.2.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/context-zone":"^2.2.0","@opentelemetry/sdk-trace-web":"^2.2.0","@opentelemetry/sdk-trace-base":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/instrumentation-fetch":"^0.208.0","@opentelemetry/instrumentation-document-load":"^0.54.0","@opentelemetry/instrumentation-user-interaction":"^0.53.0","@opentelemetry/instrumentation-xml-http-request":"^0.208.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^27.3.0","vitest":"4.0.15","esbuild":"^0.27.1","typescript":"^5.9.3","@types/node":"25.0.1","typescript-config":"workspace:*"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0"},"_npmOperationalInternal":{"tmp":"tmp/otel-browser_0.5.1_1784713768282_0.5205387239270554","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@aient/otel-browser","version":"0.6.0","private":false,"publishConfig":{"access":"public"},"description":"Minimal browser-only OpenTelemetry bootstrap for Aient","author":{"name":"Triple Alpha AB"},"license":"MIT","type":"module","sideEffects":false,"exports":{".":{"types":"./dist/types/index.d.ts","default":"./dist/index.js"},"./cdn":{"default":"./dist/cdn/index.js"}},"types":"./dist/types/index.d.ts","scripts":{"build":"node ./build.mjs","clean":"rm -rf dist .dist-tmp .dist-backup .build-lock","lint":"true","lint:fix":"true","type-check":"tsc --noEmit","test":"pnpm test:unit","test:unit":"pnpm unit-test","test:unit:watch":"pnpm unit-test-watch","unit-test":"vitest --run","unit-test-watch":"vitest","prepare":"pnpm build","size":"node -e \"const fs=require('fs');const zlib=require('zlib');const b=fs.readFileSync('dist/cdn/index.js');const gz=zlib.gzipSync(b,{level:9});const kb=(gz.length/1024).toFixed(1);const max=200;console.log('cdn gz',kb+'kb');if(gz.length>max*1024){console.error('Size limit exceeded:'+kb+'kb > '+max+'kb');process.exit(1)}\""},"dependencies":{"@opentelemetry/context-zone":"^2.2.0","@opentelemetry/core":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/instrumentation-document-load":"^0.54.0","@opentelemetry/instrumentation-fetch":"^0.208.0","@opentelemetry/instrumentation-xml-http-request":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/sdk-trace-base":"^2.2.0","@opentelemetry/sdk-trace-web":"^2.2.0"},"devDependencies":{"@types/node":"25.0.1","esbuild":"^0.27.1","jsdom":"^27.3.0","typescript":"^5.9.3","typescript-config":"workspace:*","vitest":"4.0.15"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0"},"engines":{"node":">=18.19.0"},"gitHead":"1b7f83ee238e7f7783dce4f9955d92ab14152c8a","_id":"@aient/otel-browser@0.6.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-OUDiCCTEFRlFnt2emTQ4kFRRelPcb30hhem/bTHVLthYuR/bl/DprrWGkAid3tcUr+ERvrJRyygp8s61m9C5jQ==","shasum":"50b4069d2b03d69cf59b3c4dba4a96ff377fb121","tarball":"https://registry.npmjs.org/@aient/otel-browser/-/otel-browser-0.6.0.tgz","fileCount":19,"unpackedSize":2428756,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBjRip81uWV0QyvKbrvW4b2SSBQg0+gXddQd1xG7thCbAiB5U6ErjbnkGECPozQQe0XiU66cD9r08+iFmiEjfwNAYQ=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:1a4cef7d-abdd-4db2-918f-d8bfb39ca0cb"}},"directories":{},"maintainers":[{"name":"haf","email":"henrik@haf.se"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/otel-browser_0.6.0_1785524840712_0.29748901815085116"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-03T06:14:22.077Z","modified":"2026-07-31T19:07:21.323Z","0.3.0":"2026-04-03T06:14:22.363Z","0.4.0":"2026-05-07T15:28:38.219Z","0.4.1":"2026-06-08T16:38:27.239Z","0.5.0":"2026-07-20T16:19:21.528Z","0.5.1":"2026-07-22T09:49:28.445Z","0.6.0":"2026-07-31T19:07:20.910Z"},"author":{"name":"Triple Alpha AB"},"license":"MIT","description":"Minimal browser-only OpenTelemetry bootstrap for Aient","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"readme":"# @aient/otel-browser\n\nOpenTelemetry for the browser. Works out of the box, highly configurable.\n\n## Quick Start (3 lines)\n\n```bash\nnpm install @aient/otel-browser @opentelemetry/api @opentelemetry/api-logs\n```\n\n```ts\nimport { registerOTelBrowser } from '@aient/otel-browser'\n\nregisterOTelBrowser({ serviceName: 'my-web-app' })\n```\n\nDone. Traces go to `https://ingest.aient.ai/v1/traces`, logs to `/v1/logs`.\n\n### Local Development\n\nFor local development with a local collector:\n\n```ts\nregisterOTelBrowser({\n  serviceName: 'my-web-app',\n  exporterUrl: 'http://localhost:4318',\n})\n```\n\n### Production: Aient.dev Ingest\n\nFor production with Aient authentication:\n\n```ts\nregisterOTelBrowser({\n  serviceName: 'my-web-app',\n  // exporterUrl defaults to https://ingest.aient.ai\n  publishableKey: 'pk_live_11...',\n})\n```\n\n---\n\n## Full Example (all options)\n\n```ts\nimport { registerOTelBrowser } from '@aient/otel-browser'\n\nconst sdk = registerOTelBrowser({\n  // Identity\n  serviceName: 'my-web-app',\n  // Caller-owned installation ID (persist/rotate according to your consent policy)\n  installationId: '0198d2f4-1111-7111-8111-111111111111',\n\n  // Aient auth\n  publishableKey: 'pk_xxx',\n\n  // Release metadata (CRITICAL for source mapping)\n  release: {\n    commit: process.env.NEXT_PUBLIC_COMMIT_SHA,  // or 'abc1234'\n    branch: process.env.NEXT_PUBLIC_COMMIT_REF,  // or 'main'\n    version: '1.0.0',\n    environment: 'production',\n  },\n\n  // Export - base URL, SDK derives /v1/traces and /v1/logs\n  exporterUrl: 'https://ingest.aient.ai',\n  exporter: 'http/json',\n  exporterHeaders: { 'x-tenant-id': 'acme' },\n  credentials: 'include',  // for CORS\n\n  // Logs (auto-derived to /v1/logs)\n  logs: {\n    exporter: 'http/json',\n  },\n\n  // Instrumentations\n  instrumentations: ['auto'],  // document-load, exact click capture, xhr, fetch\n  fetch: {\n    ignoreUrls: [/\\/healthz?$/, /analytics\\.js$/],\n    propagateContextUrls: [/^https:\\/\\/api\\.myapp\\.com/],\n  },\n\n  // Capture\n  captureUnhandledErrors: true,  // window.onerror, unhandledrejection (default: true)\n  captureConsoleLogs: true,      // console.* as OTLP logs (default: false)\n  includeUserAgent: false,       // privacy default\n\n  // Initial user context\n  user: { userId: 'user_123', pseudoId: 'anon_abc', role: 'admin' },\n\n  // Dynamic correlation context for future spans and outgoing baggage\n  contextAttributes: { 'business.id': 'business_123' },\n\n  // Debug\n  logLevel: 'DEBUG',\n})\n\n// Update user on login/logout without changing the installation ID\nsdk.identify({ userId: 'user_456', pseudoId: 'pseudo_abc' })\nsdk.clearUser()\nsdk.identify({ userId: 'user_789' })\n\n// Replace context after a business/workspace switch; clear it on logout\nsdk.setContextAttributes({ 'business.id': 'business_456' })\nsdk.setContextAttributes(null)\n```\n\n`attributes` and `contextAttributes` have different lifecycles. Use `attributes` for static resource metadata such as deployment or service facts. Use `contextAttributes` for mutable correlation values such as the active business, account, or workspace. Each span captures the current dynamic snapshot when it starts, so updates do not retroactively change in-flight or ended spans.\n\nDynamic context is also propagated as W3C baggage on outgoing Fetch and XHR requests. Treat it only as telemetry correlation data: browser-provided `app.installation.id`, `enduser.id`, and `enduser.pseudo.id` are untrusted claims and must never authorize access or replace server-side identity/session checks. Email and role are never propagated. Keys under `enduser.*` and `app.installation.id` are SDK-owned and omitted from generic context.\n\n`http/json` is the only bundled OTLP transport. Legacy `http/protobuf` values are ignored at runtime and fall back to JSON.\n\n## OTLP JSON protocol contract\n\nThe SDK exports traces and logs as OTLP/HTTP JSON protobuf payloads with `Content-Type: application/json`.\n\nThe serializer follows the OTLP JSON mapping used by the OpenTelemetry protocol:\n\n- request envelopes are `ExportTraceServiceRequest` and `ExportLogsServiceRequest` JSON objects (`resourceSpans` and `resourceLogs`);\n- JSON field names are lowerCamelCase, for example `startTimeUnixNano` and `droppedAttributesCount`;\n- trace IDs and span IDs are hex strings, not base64;\n- 64-bit timestamps and integer attribute values are decimal strings;\n- enum fields such as span kind, span status, and log severity are encoded as numbers;\n- arbitrary byte attributes are base64 strings;\n- spans and logs are grouped by resource and instrumentation scope, including schema URLs when present.\n\n`@aient/otel-browser` does not bundle `protobufjs`, `@opentelemetry/otlp-transformer`, or `@opentelemetry/otlp-exporter-base`. Protocol-sensitive serializer behavior is covered by `test/otlp-json-serializer.test.ts`, and dependency regressions are covered by `test/package-contract.test.ts`.\n\n---\n\n## Environment Variables (via Build Tools)\n\nBrowsers don't have runtime environment variables, but you can inject them at build time using your bundler:\n\n**Next.js (`next.config.mjs`):**\n```js\n// Automatically available as process.env.NEXT_PUBLIC_*\n// Set in .env or CI environment\n```\n\n**Vite (`vite.config.ts`):**\n```ts\nexport default defineConfig({\n  define: {\n    'import.meta.env.VITE_OTEL_ENDPOINT': JSON.stringify(process.env.OTEL_EXPORTER_OTLP_ENDPOINT),\n    'import.meta.env.VITE_COMMIT_SHA': JSON.stringify(process.env.COMMIT_SHA),\n  }\n})\n```\n\n**Webpack:**\n```js\nnew webpack.DefinePlugin({\n  'process.env.OTEL_ENDPOINT': JSON.stringify(process.env.OTEL_EXPORTER_OTLP_ENDPOINT),\n})\n```\n\n---\n\n## React / Next.js Integration\n\nUse a client-only component at a long-lived application boundary: registering during render can duplicate exporters. Register only in the initialization effect, and update identity in a separate effect without recreating the SDK. `shutdown()` synchronously detaches instrumentations and global OpenTelemetry registrations before asynchronously draining providers, so an immediate React Strict Mode remount starts a clean generation. Tracer and logger handles cached from the global OpenTelemetry APIs follow the active generation and become no-ops while no `@aient/otel-browser` SDK is registered.\n\nThis package is a browser telemetry bootstrap and must be the sole owner of the page's OpenTelemetry trace, context, propagation, and logs globals. Registration throws without replacing or removing a host application's existing OpenTelemetry globals.\n\n```tsx\n'use client'\nimport { useEffect, useRef } from 'react'\nimport { registerOTelBrowser, type BrowserSDK } from '@aient/otel-browser'\n\nexport function TelemetryInit({\n  userId,\n  pseudoId,\n  installationId,\n}: {\n  userId?: string | null\n  pseudoId?: string | null\n  installationId?: string\n}) {\n  const sdkRef = useRef<BrowserSDK | null>(null)\n\n  useEffect(() => {\n    const sdk = registerOTelBrowser({\n      publishableKey: process.env.NEXT_PUBLIC_AIENT_PUBLISHABLE_KEY!,\n      serviceName: process.env.NEXT_PUBLIC_OTEL_SERVICE_NAME ?? 'web',\n      installationId,\n      ...(process.env.NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT\n        ? { exporterUrl: process.env.NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT }\n        : {}),\n      release: {\n        commit: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA ?? 'dev',\n        branch: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF ?? 'local',\n        environment: process.env.NEXT_PUBLIC_VERCEL_ENV ?? 'development',\n      },\n    })\n    sdkRef.current = sdk\n    return () => {\n      void sdk.shutdown()\n    }\n  }, [])\n\n  useEffect(() => {\n    if (userId || pseudoId) {\n      sdkRef.current?.identify({\n        ...(userId ? { userId } : {}),\n        ...(pseudoId ? { pseudoId } : {}),\n      })\n    } else {\n      sdkRef.current?.clearUser()\n    }\n  }, [userId, pseudoId])\n\n  return null\n}\n```\n\n```tsx\n// app/layout.tsx (App Router)\nimport { cookies } from 'next/headers'\n\nexport default async function RootLayout({ children }) {\n  const user = await getCurrentUser()\n  const installationId = (await cookies()).get('app_installation_id')?.value\n  const pseudonymousUserId = user\n    ? (await cookies()).get('pseudonymous_user_id')?.value\n    : undefined\n  return (\n    <html>\n      <body>\n        <TelemetryInit userId={user?.id} pseudoId={pseudonymousUserId} installationId={installationId} />\n        {children}\n      </body>\n    </html>\n  )\n}\n```\n\n---\n\n## Browser ↔ server trace context\n\nThe SDK does not read a `traceparent` from HTML metadata. Browser/server\ncontinuity is established when the configured Fetch/XHR instrumentation injects\nW3C trace-context headers from an active browser span into an allowed request.\n\n---\n\n## CORS Requirements\n\nYour collector must allow:\n\n```\nAccess-Control-Allow-Origin: * (or your origin)\nAccess-Control-Allow-Headers: content-type, traceparent, baggage, authorization\nAccess-Control-Allow-Credentials: true (if using credentials)\n```\n\n---\n\n## Defaults\n\n| Feature | Default |\n|---------|---------|\n| Trace exporter | `http/json` → `https://ingest.aient.ai/v1/traces` |\n| Log exporter | `http/json` → `https://ingest.aient.ai/v1/logs` |\n| Instrumentations | document-load, one document-capture click span per event, xhr, fetch |\n| Error capture | `window.onerror`, `unhandledrejection` |\n| User agent | NOT included (privacy) |\n| Console capture | OFF |\n\n---\n\n## Identity lifecycle\n\n`installationId` represents one application installation and is emitted as the `app.installation.id` resource attribute. The generic SDK does not create or persist it. `identify()` replaces the complete user portion; `clearUser()` removes it while retaining the installation. `getIdentity()` returns a clone of the composite snapshot.\n\n```ts\nsdk.getIdentity() // { installationId: '...' }\nsdk.identify({ userId: authenticatedUser.id })\nsdk.getIdentity() // { installationId: '...', userId: '...' }\nsdk.clearUser()\nsdk.getIdentity() // { installationId: '...' }\n```\n\nUser fields are added to future spans and logs:\n\n| Attribute | Description |\n|-----------|-------------|\n| `enduser.id` | Primary user identifier |\n| `enduser.pseudo.id` | Privacy-preserving hash |\n| `enduser.email` | PII, use with caution |\n| `enduser.role` | Permission scope |\n\n`setUserContext()` and `getUserContext()` remain compatibility aliases over the same generation-owned user snapshot. Identity calls do not mutate ambient OpenTelemetry context or baggage. The span processor reads at span start, the log processor at emit, and the baggage propagator at request injection.\n\n```ts\nsdk.identify({ userId: authenticatedUser.id, pseudoId: pseudonymousUserId })\n```\n\nThe SDK emits both attributes but does not emit an identity-link event. Link events are application-domain telemetry and must define their own privacy, deduplication, and payload contract.\n\n## Lifecycle and version capabilities\n\n| Version | Relevant capability |\n|---------|---------------------|\n| `0.4.1` | User context (`setUserContext`), but no dynamic context API |\n| `0.5.0` | Adds `setContextAttributes` and `getContextAttributes` |\n| `0.5.1` | Complete instrumentation/global teardown, safe immediate re-registration, blank-error normalization, and ResizeObserver loop filtering |\n| `0.6.0` | Exact one-event/one-click capture plus flat `identify`, `clearUser`, `getIdentity`, installation correlation, and untrusted user baggage |\n\nIf a runtime method is missing, inspect the installed artifact rather than the workspace manifest:\n\n```bash\nnpm ls @aient/otel-browser\n```\n\nThen verify the resolved package in the lockfile and reinstall/rebuild the consuming app. An already-loaded older browser bundle cannot diagnose capabilities introduced by a newer package.\n\n## Dynamic Context Attributes\n\nCall `sdk.setContextAttributes()` when mutable application context changes:\n\n```ts\nsdk.setContextAttributes({\n  'business.id': 'business_123',\n  'workspace.id': 'workspace_456',\n})\n\nconst snapshot = sdk.getContextAttributes()\nsdk.setContextAttributes(null)\n```\n\nThe setter replaces the whole snapshot rather than merging it. Values are cloned on set and get. Future spans receive the snapshot at span start, while existing spans remain unchanged. Outgoing baggage preserves unrelated entries and replaces SDK-owned dynamic keys.\n\n## Click capture\n\nThe `auto` and explicit `user` selectors install one `document` capture listener per SDK generation. Every eligible DOM click reaching it creates one synchronous point span named `click`, even when target handlers later call `preventDefault()`, return `false`, or stop propagation. The SDK does not patch application listeners, debounce events, cache fingerprints, or deduplicate exports. Because the span ends at the capture boundary, it is not an active parent around later application handlers.\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}