@moonbase.sh/storefront 2.4.2 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,14 +45,14 @@ When you load the widget via the CDN script tag:
45
45
 
46
46
  When you import from npm (`import Moonbase from '@moonbase.sh/storefront'`), `setup` still needs the DOM to be available before it runs, since there is no loader in that path.
47
47
 
48
- ## Testing pre-release builds with `?mb_version=`
48
+ ## Testing pre-release builds with `?mb_storefront_version=`
49
49
 
50
- The CDN loader recognises an `?mb_version=` query parameter for opting into a non-default storefront build on a per-page-load basis. This is intended for testing pre-release changes on a live merchant site without changing the embed code.
50
+ The CDN loader recognises an `?mb_storefront_version=` query parameter for opting into a non-default storefront build on a per-page-load basis. This is intended for testing pre-release changes on a live merchant site without changing the embed code.
51
51
 
52
- - `?mb_version=next` — loads the latest `@next` snapshot from `/storefront/next/moonbase.js`
53
- - `?mb_version=pr-<N>` — loads the snapshot from a labeled PR `<N>` from `/storefront/pr-<N>/moonbase.js` (only present while the PR carries the `release-snapshot` label)
54
- - `?mb_version=2.1.0` — pins to a specific published version from `/storefront/<version>/moonbase.js`
55
- - `?mb_version=latest` or omitted — loads the current stable release (default)
52
+ - `?mb_storefront_version=next` — loads the latest `@next` snapshot from `/storefront/next/moonbase.js`
53
+ - `?mb_storefront_version=pr-<N>` — loads the snapshot from a labeled PR `<N>` from `/storefront/pr-<N>/moonbase.js` (only present while the PR carries the `release-snapshot` label)
54
+ - `?mb_storefront_version=2.1.0` — pins to a specific published version from `/storefront/<version>/moonbase.js`
55
+ - `?mb_storefront_version=latest` or omitted — loads the current stable release (default)
56
56
 
57
57
  Don't use this to pin a production embed to a specific version — pin the `<script src>` URL instead.
58
58
 
@@ -131,3 +131,80 @@ Available events include:
131
131
  - `checkout-initiated`
132
132
  - `checkout-closed`
133
133
  - `checkout-completed`
134
+
135
+ ## Integrations
136
+
137
+ The widget can forward its commerce and auth events to common marketing/analytics SDKs without any extra glue code. Enable a provider by passing its config in `integrations`:
138
+
139
+ ```ts
140
+ Moonbase.setup('https://demo.moonbase.sh', {
141
+ integrations: {
142
+ metaPixel: { pixelId: '1234567890' },
143
+ googleAnalytics: { measurementId: 'G-XXXXXXX' },
144
+ googleTagManager: { containerId: 'GTM-XXXXXXX' },
145
+ klaviyo: { companyId: 'ABC123' },
146
+ tiktokPixel: { pixelId: 'C12345...' },
147
+ },
148
+ })
149
+ ```
150
+
151
+ The widget never loads SDK scripts itself — it only forwards to globals the host page has already initialised (`window.fbq`, `window.gtag`, `window.dataLayer`, `window.klaviyo`, `window.ttq`). If a global is missing when an event fires, the forwarding is a silent no-op (with a one-time `console.warn` so a misconfiguration is discoverable).
152
+
153
+ ### You install the SDK; Moonbase forwards to it
154
+
155
+ You load each SDK with its own official snippet, exactly as you would without Moonbase — Moonbase only needs the same id so it can forward. Load order doesn't matter: if the global appears after `setup()`, forwarding begins as soon as it's there. For example, Meta Pixel:
156
+
157
+ ```html
158
+ <!-- Your existing Meta Pixel snippet -->
159
+ <script>
160
+ !function(f,b,e,v,n,t,s){/* …standard fbq loader… */}(window,document,'script',
161
+ 'https://connect.facebook.net/en_US/fbevents.js');
162
+ fbq('init', '1234567890');
163
+ fbq('track', 'PageView');
164
+ </script>
165
+ ```
166
+
167
+ ```ts
168
+ // Hand Moonbase the same id so it can forward commerce/auth events to fbq:
169
+ Moonbase.setup('https://demo.moonbase.sh', {
170
+ integrations: { metaPixel: { pixelId: '1234567890' } },
171
+ })
172
+ ```
173
+
174
+ The same pattern applies to GA4 (`gtag`), GTM (`dataLayer`), Klaviyo (`klaviyo`), and TikTok (`ttq`): install the vendor snippet, then pass the matching id. For Klaviyo, both the modern onsite object (`klaviyo.identify()` / `klaviyo.track()`) and the legacy `klaviyo.push([...])` queue are supported automatically. The `googleTagManager.containerId` is informational/reserved — GTM reads from `window.dataLayer` regardless of which container loaded it, so it isn't used at runtime.
175
+
176
+ ### Consent
177
+
178
+ Forwarding is unconditional: Moonbase forwards to whatever SDK global is present, and relies on **that SDK's own consent state** (e.g. Google Consent Mode v2, or your CMP gating `fbq`/`ttq`). To suppress forwarding entirely until consent is granted, omit the provider from `setup()` and add it once consent lands:
179
+
180
+ ```ts
181
+ onConsentGranted(() => Moonbase.configure({ integrations: { metaPixel: { pixelId: '1234567890' } } }))
182
+ ```
183
+
184
+ `configure({ integrations })` can add, change, or remove providers at any time. Merge semantics apply per provider: pass a provider to add or update it, pass it as `undefined` (or `null`) to remove it, and omit it to leave it unchanged — so granting one provider after consent never disturbs the others.
185
+
186
+ ```ts
187
+ // Stop forwarding to Meta Pixel, leave every other provider running:
188
+ Moonbase.configure({ integrations: { metaPixel: undefined } })
189
+ ```
190
+
191
+ ### Identity
192
+
193
+ `signed-in` / `signed-up` forward an identify call when an email/id is available (Meta advanced match, GA4 `user_id`, Klaviyo identify, TikTok identify). On `signed-out`, Moonbase clears what each SDK supports (GA4 `user_id` is reset, GTM gets a `logout` push); Meta, TikTok, and Klaviyo expose no per-user logout, so their profiles persist for the session.
194
+
195
+ ### Data conventions
196
+
197
+ Forwarded order `value` is the amount the customer pays — `total.due`, post-discount and **tax-inclusive** (no separate tax field is sent). Per-item prices are the net (post-discount) unit price. `checkout-completed` events carry the order id as a dedup key (Meta `eventID`, TikTok `event_id`, GA4/GTM `transaction_id`) so a completion isn't double-counted.
198
+
199
+ ### Event mapping
200
+
201
+ | Moonbase event | Meta Pixel | GA4 | GTM (`dataLayer`) | Klaviyo | TikTok Pixel |
202
+ | -------------------- | ----------------------- | -------------------- | -------------------- | ------------------------ | --------------------- |
203
+ | `added-to-cart` | `AddToCart` | `add_to_cart` | `add_to_cart` | `Added to Cart` | `AddToCart` |
204
+ | `checkout-initiated` | `InitiateCheckout` | `begin_checkout` | `begin_checkout` | `Started Checkout` | `InitiateCheckout` |
205
+ | `checkout-completed` | `Purchase` | `purchase` | `purchase` | `Placed Order` | `CompletePayment` |
206
+ | `signed-in` | advanced match | `login` + `user_id` | `login` | `identify` | `identify` |
207
+ | `signed-up` | `CompleteRegistration` | `sign_up` + `user_id`| `sign_up` | `identify` | `CompleteRegistration`|
208
+ | `signed-out` | — | clears `user_id` | `logout` | — | — |
209
+
210
+ For any event not listed (or a provider that isn't built in), use `Moonbase.on(...)` and forward by hand.
@@ -18,8 +18,36 @@ declare type DeepPartial<T> = T extends object ? {
18
18
 
19
19
  export declare const eventEmitterKey: InjectionKey<MoonbaseEventEmitter>;
20
20
 
21
+ export declare interface GoogleAnalyticsConfig {
22
+ measurementId: string;
23
+ }
24
+
25
+ export declare interface GoogleTagManagerConfig {
26
+ /**
27
+ * Informational/reserved. GTM containers read from `window.dataLayer`
28
+ * regardless of which container loaded them, so this is not used at runtime.
29
+ */
30
+ containerId?: string;
31
+ }
32
+
21
33
  export declare const instanceKey: InjectionKey<MoonbaseInstance>;
22
34
 
35
+ export declare interface IntegrationsConfig {
36
+ metaPixel?: MetaPixelConfig;
37
+ googleAnalytics?: GoogleAnalyticsConfig;
38
+ googleTagManager?: GoogleTagManagerConfig;
39
+ klaviyo?: KlaviyoConfig;
40
+ tiktokPixel?: TikTokPixelConfig;
41
+ }
42
+
43
+ export declare interface KlaviyoConfig {
44
+ companyId: string;
45
+ }
46
+
47
+ export declare interface MetaPixelConfig {
48
+ pixelId: string;
49
+ }
50
+
23
51
  declare const Moonbase_2: MoonbaseImpl;
24
52
  export default Moonbase_2;
25
53
 
@@ -97,6 +125,8 @@ declare class MoonbaseImpl implements MoonbaseInstance {
97
125
  private pinia;
98
126
  private storefront;
99
127
  private options;
128
+ private integrations;
129
+ private completedOrderIds;
100
130
  setup(url: string, options?: DeepPartial<MoonbaseOptions>): Promise<void>;
101
131
  configure(options: DeepPartial<MoonbaseOptions>): void;
102
132
  on<TEvent extends MoonbaseEvent>(eventType: TEvent, callback: (event: MoonbaseEventArgs[TEvent]) => void): void;
@@ -256,7 +286,7 @@ export declare interface MoonbaseIntentArgs {
256
286
  [MoonbaseIntent.ViewAbout]: never;
257
287
  }
258
288
 
259
- declare interface MoonbaseOptions {
289
+ export declare interface MoonbaseOptions {
260
290
  toolbar: {
261
291
  enabled: boolean;
262
292
  location: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
@@ -329,6 +359,20 @@ declare interface MoonbaseOptions {
329
359
  * of the widget's automatic counter-scaling and match the host's density.
330
360
  */
331
361
  disableViewportCompensation: boolean;
362
+ /**
363
+ * Opt in to built-in forwarding of storefront events to common
364
+ * marketing/analytics SDKs. Each provider is enabled by supplying its
365
+ * config object. The widget never loads SDK scripts — it only forwards
366
+ * to globals the host page has already initialised (e.g. `window.fbq`,
367
+ * `window.gtag`, `window.dataLayer`, `window.klaviyo`, `window.ttq`).
368
+ * If a provider's global is missing at the time of an event, the
369
+ * forwarding is a silent no-op.
370
+ */
371
+ integrations: IntegrationsConfig;
372
+ }
373
+
374
+ export declare interface TikTokPixelConfig {
375
+ pixelId: string;
332
376
  }
333
377
 
334
378
  export declare const urlKey: InjectionKey<string>;