billdogeng-astro
v1.0.0-beta.1
Published
BilldogEng SDK for Astro — SSR-safe, island-idiomatic wrapper over the BillDog engagement suite (analytics, surveys, in-app messaging, remote feature flags).
Maintainers
Readme
billdogeng-astro
The BillDog engagement suite for Astro — a thin, SSR-safe,
island-idiomatic wrapper over the existing browser SDKs (@billdog.io/web,
@billdog.io/analytics, @billdog.io/survey-core).
It surfaces everything the engagement suite offers, the Astro way:
- Analytics —
capture,identify,group - Surveys — fetch, render (
<Survey/>/renderSurvey), and submit - In-app messaging — trigger placements (
showInAppMessages) - Feature flags — remote / server-authoritative (
getFeatureFlag)
Feature flags are evaluated on the BillDog backend. This package does no local bucketing and contains no murmurhash — targeting is server-side only.
How it works (Astro islands)
Astro has no React-style context/provider. Instead this SDK uses a tiny
browser-global store shared across every island on the page. <BilldogProvider/>
emits a client-only <script> that boots the engagement client; every other
helper (capture, getFeatureFlag, renderSurvey, …) talks to that shared
client. Calls made before init are queued and flushed once the client is ready.
Everything is SSR-safe: importing the package touches no window/document,
.astro frontmatter runs on the server with no side effects, and every helper
degrades to a no-op during SSR / static builds.
Install
npm install billdogeng-astro @billdog.io/web @billdog.io/analytics @billdog.io/survey-coreastro is a peer dependency. The three BillDog browser SDKs are optional peers —
install the ones whose features you use.
Quickstart
Mount the provider once in your layout:
---
// src/layouts/Layout.astro
import { BilldogProvider } from 'billdogeng-astro/components';
---
<html lang="en">
<head>
<BilldogProvider
apiKey={import.meta.env.PUBLIC_BILLDOG_API_KEY}
projectId={import.meta.env.PUBLIC_BILLDOG_PROJECT_ID}
customerId="user_42"
/>
</head>
<body>
<slot />
</body>
</html>The provider renders nothing visible. The client only boots in the browser, so it is safe in statically rendered and SSR pages alike.
Analytics
Use the helpers from any client-side <script> (or any island/framework
component):
<button id="buy">Buy</button>
<script>
import { capture, identify, group } from 'billdogeng-astro';
document.getElementById('buy')?.addEventListener('click', () => {
identify('user_42', { plan: 'pro' });
group('company', 'acme', { seats: 12 });
capture('checkout_started', { value: 49.0 });
});
</script>Calls made before <BilldogProvider/> finishes initialising are queued and
flushed automatically — no ordering footguns.
Feature flags (remote)
<div id="banner" hidden>Welcome!</div>
<script>
import { subscribeFeatureFlag, getFeatureFlag } from 'billdogeng-astro';
// One-shot read (returns the default until flags load):
const theme = getFeatureFlag('home-theme', 'classic');
// Live subscription — fires now and on every remote re-evaluation:
subscribeFeatureFlag('new-banner', (enabled) => {
const el = document.getElementById('banner');
if (el) el.hidden = !enabled;
}, false);
</script>Values come from the backend's flag-evaluation response cached by the underlying SDK. There is no client-side bucketing.
Surveys
Drop-in component:
---
import { Survey } from 'billdogeng-astro/components';
---
<Survey surveyId="svy_nps" class="feedback" />Or render imperatively into any element:
<div id="survey-host"></div>
<script>
import { renderSurvey } from 'billdogeng-astro';
const host = document.getElementById('survey-host');
if (host) {
renderSurvey(host, {
surveyId: 'svy_nps',
onSubmit: (result) => console.log('submitted', result.responseId),
});
}
</script>Lower level, fetch + submit yourself:
import { fetchSurvey, submitSurvey } from 'billdogeng-astro';
const survey = await fetchSurvey('svy_nps');
await submitSurvey('svy_nps', [{ question_id: 'q1', answer_number: 9 }]);In-app messaging
import { showInAppMessages } from 'billdogeng-astro';
showInAppMessages('help-center');API
| Export | Kind | Purpose |
| --- | --- | --- |
| <BilldogProvider apiKey projectId /> | .astro | Init + client boot (SSR-safe, client-only). |
| <Survey surveyId /> | .astro | Fetch + render + submit a survey. |
| initBilldog(config, opts?) | fn | Imperative init (returns null on the server). |
| capture / identify / group / reset | fn | Analytics (queue-aware, SSR no-op). |
| showInAppMessages(placementId?) | fn | Trigger an in-app message placement. |
| getFeatureFlag(key, default?) | fn | Remote flag value (boolean or string variant). |
| subscribeFeatureFlag(key, cb, default?) | fn | Live flag subscription. |
| reloadFeatureFlags() | fn | Force a remote flag re-evaluation. |
| fetchSurvey / listSurveys / submitSurvey | fn | Survey data access. |
| renderSurvey(el, opts) | fn | Vanilla-DOM survey renderer. |
| onBilldogReady(cb) / isReady() / getClient() | fn | Lifecycle. |
| createBilldogClient(config, deps?) | fn | Low-level client builder (advanced). |
SSR / static rendering
- Importing
billdogeng-astronever toucheswindow/document. initBilldogreturnsnullon the server; the client only boots in the browser.- Analytics/messaging helpers are no-ops on the server.
getFeatureFlagreturns its default on the server.<BilldogProvider/>and<Survey/>emit empty markup on the server and hydrate via client-only scripts.
License
MIT
