back to homepage

install SDK

copy-paste single-file SDK for Chrome extensions (MV3) and web apps

0. Why copy-paste, not npm

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.

  • Zero runtime dependencies: the file is fully self-contained
  • No remote code execution: no eval, no dynamic import(), no <script> injection — passes Chrome Web Store MV3 review by design
  • Zero permissions required: the SDK does not call chrome.cookies, chrome.storage, chrome.webRequest, or chrome.tabs
  • Auditable size: 4,303 bytes, unminified. You can read the whole SDK in a few minutes before adopting it.

1. Add datibase.mjs to your extension

Create 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.

2. Allow the datibase endpoint in your manifest

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/*"]
}

3. Use it from any context

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" });

4. Privacy guarantees

  • No cookies, no persistent storage: visitor identifiers are generated in memory and reset every UTC day
  • No PII transmission: URL parameters, referrer query strings, and event property values containing sensitive keys or email patterns are stripped server-side before storage
  • DNT and GPC respected: the SDK skips network calls entirely when the browser signals doNotTrack === "1" or globalPrivacyControl
  • GDPR / CCPA compliant: see the full privacy policy for what is and isn’t collected