copy-paste single-file SDK for Chrome extensions (MV3) and web apps
Datibase ships as a single audited file that you copy into your extension’s source tree. There is no npm install, no dependency tree, no supply-chain surface — you review the code once and it becomes yours.
eval, no dynamic import(), no <script> injection — passes Chrome Web Store MV3 review by designchrome.cookies, chrome.storage, chrome.webRequest, or chrome.tabsCreate a file at src/lib/datibase.mjs (or any path you prefer) in your extension project, and paste the contents below.
Datibase SDK single-file distribution
/*!
* @datibase/sdk v0.1.0
* Cookie-free, PII-safe analytics SDK for Chrome extensions (MV3) and web apps.
*
* License: MIT
* Built: 2026-07-20T04:17:18.272Z
* Source: https://github.com/datibase (single-file distribution — audit and paste)
*
* このファイルは監査してコピー & ペーストすることを想定している。
* ランタイム依存: なし / 動的コード実行: なし / cookie 使用: なし
*/
// packages/sdk/src/transport.ts
var isDoNotTrackEnabled = () => {
const g = globalThis;
const nav = g.navigator;
if (!nav) return false;
if (nav.doNotTrack === "1") return true;
if (nav.globalPrivacyControl === true) return true;
return false;
};
var send = async ({ url, body, debug }) => {
if (isDoNotTrackEnabled()) {
if (debug) console.log("[Datibase] DNT enabled \u2014 skip", url);
return;
}
try {
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
credentials: "omit",
keepalive: true
});
if (debug) console.log("[Datibase] sent", url, res.status);
} catch (error) {
if (debug) console.warn("[Datibase] send failed", url, error);
}
};
// packages/sdk/src/visitor.ts
var simpleHash = (input) => {
let hash = 0;
for (let i = 0; i < input.length; i++) {
const char = input.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash = hash & hash;
}
return Math.abs(hash).toString(36);
};
var readGlobals = () => {
const g = globalThis;
return {
navigator: g.navigator ?? {},
location: g.location ?? {}
};
};
var todayUTC = () => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
var generateDailyVisitorId = () => {
const { navigator: nav, location: loc } = readGlobals();
const parts = [
nav.userAgent ?? "",
nav.language ?? "",
loc.hostname ?? "",
todayUTC()
];
return simpleHash(parts.join("|"));
};
// packages/sdk/src/index.ts
var DEFAULT_ENDPOINT = "https://datibase.dev";
var NotInitializedError = class extends Error {
constructor() {
super("[Datibase] init({ key }) \u3092\u5148\u306B\u547C\u3093\u3067\u304F\u3060\u3055\u3044");
this.name = "NotInitializedError";
}
};
var config = null;
var requireConfig = () => {
if (!config) {
console.warn(new NotInitializedError().message);
throw new NotInitializedError();
}
return config;
};
var datibase = {
init({ key, endpoint, debug }) {
if (!key || typeof key !== "string") {
throw new Error("[Datibase] init({ key }) \u306B\u306F websiteId \u304C\u5FC5\u8981\u3067\u3059");
}
config = {
key,
endpoint: endpoint?.replace(/\/$/, "") ?? DEFAULT_ENDPOINT,
debug: debug ?? false
};
if (config.debug) {
console.log("[Datibase] initialized", { endpoint: config.endpoint });
}
},
async trackView(path, options) {
const { key, endpoint, debug } = requireConfig();
const docRef = globalThis.document?.referrer ?? "";
await send({
url: `${endpoint}/api/analytics/pageview`,
body: {
websiteId: key,
visitorId: generateDailyVisitorId(),
path,
title: options?.title,
referrer: options?.referrer ?? docRef,
timestamp: (/* @__PURE__ */ new Date()).toISOString()
},
debug
});
},
async track(eventName, properties) {
const { key, endpoint, debug } = requireConfig();
await send({
url: `${endpoint}/api/analytics/event`,
body: {
websiteId: key,
visitorId: generateDailyVisitorId(),
eventName,
properties: properties ?? {},
timestamp: (/* @__PURE__ */ new Date()).toISOString()
},
debug
});
},
async identify({ customerId }) {
const { key, endpoint, debug } = requireConfig();
if (!customerId) {
throw new Error("[Datibase] identify({ customerId }) \u304C\u5FC5\u8981\u3067\u3059");
}
await send({
url: `${endpoint}/api/analytics/identify`,
body: {
websiteId: key,
visitorId: generateDailyVisitorId(),
customerId
},
debug
});
}
};
var src_default = datibase;
var _resetForTests = () => {
config = null;
};
export { _resetForTests, datibase, src_default as default };
integrity — verify the copy against the following digest
sha256: 6d20a0f254eedd7c458a7899fac244188db72f65c77edebdb9871f8fec654949
run shasum -a 256 src/lib/datibase.mjs locally and confirm the value matches.
Add a single entry to host_permissions. No other permission is required.
manifest.json snippet with datibase host permission
{
"manifest_version": 3,
"name": "Your Extension",
"version": "1.0.0",
"host_permissions": ["https://datibase.dev/*"]
}Works in service workers, popups, side panels, and content scripts. Requires no document — safe to call from an MV3 service worker.
Datibase SDK usage example
import { datibase } from "./lib/datibase.mjs";
// 1. Initialize once (typically in your service worker or entry point).
datibase.init({ key: "wbs_xxx" });
// 2. Track explicit "views" — pick whatever fits your extension.
datibase.trackView("popup");
// 3. Track custom events.
await datibase.track("install_button_clicked", { plan: "pro" });
// 4. Link an authenticated customer to their traffic (optional).
await datibase.identify({ customerId: "cus_xxx" });doNotTrack === "1" or globalPrivacyControl