@birdie-so/snippet

中文文档
1.5.0发布于 2026/11/05MITTypeScriptES Module零依赖近 30 天下载 44.1万

Helper for integrating the Birdie screen recording snippet into modern JavaScript apps. Requires a Birdie account.

原始使用文档
文档目录12 节
  1. 🚀 Installation
  2. ✨ Quick Start
  3. React / Vue / Angular / JS
  4. 🧠 How It Works
  5. 🎬 Recorder launcher (Web SDK)
  6. 📱 Mobile devices
  7. 🔒 Subresource Integrity (SRI)
  8. 🧩 Advanced
  9. Get Birdie instance later
  10. 📘 Docs
  11. 🛠 Support
  12. 📄 License

@birdie-so/snippet

Easily integrate the Birdie screen recording snippet into your application using modern frameworks like React, Vue, Angular, or plain JavaScript — with full control over initialization, metadata, and event hooks.

⚡ This package is a helper utility for integrating Birdie.
You must have a Birdie account and a valid clientId to use this package.
It does not work on its own — visit https://app.birdie.so to get started.

⚡ The core logic is still loaded from our CDN. This package is just a light wrapper for easier integration and customization.

npm license


🚀 Installation

npm install @birdie-so/snippet
# or
yarn add @birdie-so/snippet

✨ Quick Start

React / Vue / Angular / JS

import { initBirdie } from "@birdie-so/snippet";

initBirdie({
  clientId: "YOUR_CLIENT_ID", // required
  contact: {
    email: "[email protected]" // required to get logs capture
  }

  // Optional metadata available to recordings
  metadata: {
    user: {
      id: "123",
      email: "[email protected]",
    },
  },

  // Optional setting to remove response bodies when collecting logs
  settings: {
    privacy: {
      mask_response_body: true
    }
  },

  // Optional hook once Birdie is ready
  onReady(birdie) {
    // you can register for the following events
    birdie.on("recorderOpen", (data) => {
      console.log("Recorder tab is opened", data);
    });
    birdie.on("start", (data) => {
      console.log("Recording started", data);
      birdie.metadata = { dynamicKey: "value" };
    });
    birdie.on("pause", (data) => {
      console.log("Recording paused", data);
    });
    birdie.on("resume", (data) => {
      console.log("Recording resumed", data);
    });
    birdie.on("stop", (data) => {
      console.log("Recording stopped", data);
    });
    birdie.on("restart", (data) => {
      console.log("Recording restarted", data);
    });
    birdie.on("captureStarted", (data) => {
      console.log("Capturing logs started", data);
    });
    birdie.on("captureStopped", (data) => {
      console.log("Capturing logs stopped", data);
    });
    birdie.on("recordingSent", (data) => {
      // data.link contains the link to the video
      console.log("A new recording has been sent", data);
    });
    birdie.on("recorderClose", (data) => {
      console.log("Recorder tab was closed", data);
    });
    birdie.on("error", (error) => {
      console.log("Something went wrong", error);
    });

    // you can also update data after initialization
    birdie.update({
        contact: {
            email: "[email protected]"
        },
        metadata: {
            parameter: "value"
        }
    });
  }

});

🧠 How It Works

This package:

  • Injects the Birdie CDN snippet dynamically using your clientId.
  • Sets global window.birdieSettings before loading.
  • Registers event callbacks once the Birdie SDK is ready (window.birdie is available).

Your original snippet like this:

<script>
  window.birdieSettings = {
    /* ... */
  };
</script>
<script src="https://cf.birdie.so/widget/embed/v3/YOUR_CLIENT_ID"
        integrity="sha384-7rC8M0J6DWvTouEw7T+c33g2KZtxGjkUe1CxynqsSx9fAHdgzhxr64PaLk7g4un0"
        crossorigin="anonymous"></script>

Is now handled via code with initBirdie().


🎬 Recorder launcher (Web SDK)

To open the Birdie recorder from a button, link or element of your own — a support form, a help center — add the launcher option. It loads the Web SDK (a separate, signed script from cdn.birdie.so/websdk/) next to the snippet. Nothing launcher-related is loaded when the option is absent.

initBirdie({
  clientId: "YOUR_CLIENT_ID",
  contact: { email: "[email protected]" },

  launcher: true,
  // or: launcher: { trigger: "#record-button", tag: "support-form", autoClose: true, chip: true }

  onReady(birdie) {
    birdie.on("recorderOpen",  () => console.log("recorder window opened"));
    birdie.on("start",         () => console.log("recording started"));
    birdie.on("stop",          () => console.log("recording stopped"));
    birdie.on("recordingSent", (d) => console.log("sharing link:", d.link));
    birdie.on("recorderClose", () => console.log("recorder window closed"));

    birdie.launcher.open();    // also close(), toggle(), opened(), closeRecorder()
  },
});

Any element with the class birdieWebsdk_open opens the recorder when clicked; trigger adds a selector of your own. While the recorder window is open, a small chip bottom right ("Recorder open", "Recording", "Sending") brings it back to front; it appears only in browsers where the recorder's floating controls cannot open (Safari), chip: true shows it everywhere, chip: false never.

onReady fires as soon as either the snippet runtime or the launcher is ready, so it works on a page where only the launcher ends up running (a help center on a domain the snippet is not authorized for). Events from the launcher carry source: "websdk"; on a page running both, the same recording can be reported by each, a second apart.

With launcher set, window.birdie exists from the moment initBirdie() returns, so birdie.on(...) can be called at once; getBirdieInstance() returns null until a runtime is actually ready. Without it, nothing changes: the snippet runtime defines window.birdie as before.


📱 Mobile devices

Birdie does not record on phones or tablets. Since 1.2.3, initBirdie() detects those devices up front (same rule as the Birdie runtime: iPhone/iPod, Android phones, iPad, Windows Phone/BlackBerry, and browsers announcing userAgentData.mobile) and does not load the snippet at all — a mobile page view makes zero requests to Birdie.

Your integration code needs no device check of its own: on mobile, window.birdie is still provided as an inert object with the same surface (on, off, emit, update, setContact, setMetadata, contact, metadata, settings, and a launcher whose open() emits an error event), and onReady / getBirdieInstance() callbacks still fire. Events simply never occur, because nothing records. The inert object carries a non-enumerable __birdieMobileStub: true if you ever need to tell it apart.

Android tablets and desktop browsers behave exactly as before.


🔒 Subresource Integrity (SRI)

initBirdie() loads the Birdie loader from a versioned, immutable URL and pins it with Subresource Integrity. The browser hashes the file it receives and refuses to execute it unless the hash matches, so the loader — which carries the public key that verifies Birdie's signed manifest — cannot be swapped, even by someone who controls the host serving it.

From v2, the loader also checks the snippet bundle (main.js) against its sha384 in that signed manifest, and the bundle checks every file it loads after it, so everything that runs on your page is verified by content.

From v3, the public key the loader carries belongs to a signing key generated inside AWS KMS, which has never left it, and the loader accepts only that key's signature. v1 and v2 keep working but trust an older key: upgrade to this release to move to the new one.

The pin ships inside this package, which your lockfile already pins by content, so the trust anchor does not come from the host it protects.

Loader versionURLIntegrity (sha384)
v3https://cf.birdie.so/widget/embed/v3/{CLIENT_ID}sha384-7rC8M0J6DWvTouEw7T+c33g2KZtxGjkUe1CxynqsSx9fAHdgzhxr64PaLk7g4un0
v2https://cf.birdie.so/widget/embed/v2/{CLIENT_ID}sha384-4c5NWkB8H0CK3H/BaPcvusHR93UZ/JUqI5ofd1qTowWf9zCvnz+nzDNSg+5Opw8E
v1https://cf.birdie.so/widget/embed/v1/{CLIENT_ID}sha384-UpHM1+1SRGw5d/lkhatup8ShhdrItyJ50qC2whsmcKcl9Xzubnhc+Vq5TXcP8VnJ

Verify it yourself at any time:

curl -s -H "Origin: https://YOUR_APP_DOMAIN" https://cf.birdie.so/widget/embed/v3/YOUR_CLIENT_ID \
  | openssl dgst -sha384 -binary | openssl base64 -A

Snippet updates do not require re-pinning. New Birdie versions ship through the signed manifest that the loader verifies at runtime; the loader itself changes rarely, and when it does we publish a new version (v4, …) while the older ones keep being served — so an application pinned to v1, v2 or v3 keeps working until it upgrades this package.

The Origin header above matters: without it (or from a domain not yet authorized for your client ID) CloudFront answers with a short "Birdie is not running here" script instead of the loader, and the hash will not match.

SRI is optional: if your setup cannot use it, remove the integrity and crossorigin attributes from the tag above (or load the unversioned URL). The manifest signature check still applies either way.


🧩 Advanced

Get Birdie instance later

import { getBirdieInstance } from "@birdie-so/snippet";

getBirdieInstance((birdie) => {
  birdie.on("start", () => {
    console.log("Recording started!");
  });
});

Or synchronously:

const birdie = getBirdieInstance();
if (birdie) {
  birdie.metadata = { key: "value" };
}

📘 Docs

For full documentation and integration examples, visit our docs page


🛠 Support

Need help? Reach out to us at [email protected]


📄 License

MIT

版本与发布记录

@birdie-so/snippet 共发布 21 个版本,首次发布于 2025/04/24;过去 12 个月发布了 16 个版本。

版本发布日期距今
1.5.0latest2026/11/053 天前
1.4.02026/11/044 天前
1.3.12026/10/2019 天前
1.3.02026/10/2019 天前
1.2.32026/09/131 个月前
1.2.22026/08/192 个月前

关于 @birdie-so/snippet 的常见问题

@birdie-so/snippet 是什么?

Helper for integrating the Birdie screen recording snippet into modern JavaScript apps. Requires a Birdie account.

如何安装 @birdie-so/snippet?

在项目目录运行 npm install @birdie-so/snippet,或使用 pnpm add / yarn add / bun add。

@birdie-so/snippet 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@birdie-so/snippet 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@birdie-so/snippet 可以商用吗?

@birdie-so/snippet 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@birdie-so/snippet 的下载量有多少?

根据 npm 官方下载统计,@birdie-so/snippet 在 2026/10/08 – 2026/11/06 这 30 天内被下载 440,523 次,日均约 14,684 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@birdie-so/snippet 还在维护吗?

最新版本 1.5.0 发布于 2026/11/05(3 天前);至今共发布 21 个版本,其中过去 12 个月发布了 16 个;首次发布于 2025/04/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。