@moonbase.sh/storefront 3.2.0 → 3.3.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
@@ -83,7 +83,7 @@ Moonbase.checkout()
83
83
  Moonbase.view_products()
84
84
  ```
85
85
 
86
- All intents are snake_case methods on the `Moonbase` instance (for example `view_product`, `manage_subscription`, `redeem_voucher`).
86
+ All intents are snake_case methods on the `Moonbase` instance (for example `view_product`, `manage_subscription`, `redeem_voucher`, `join_group`).
87
87
 
88
88
  ## Configure behavior and theme
89
89
 
@@ -140,6 +140,47 @@ A redirected buyer is always brought back to your page once they've paid, so
140
140
  The hosted checkout stays anonymous for the trip — it prefills from the order rather
141
141
  than signing the buyer into a Moonbase account, matching the overlay's behavior.
142
142
 
143
+ ### Customer groups
144
+
145
+ If you keep customer lists in Moonbase and have opened one to public sign-ups,
146
+ name it by ID and the widget enrolls people who use the matching form:
147
+
148
+ ```ts
149
+ Moonbase.configure({
150
+ groups: {
151
+ signUp: ['newsletter-2026'],
152
+ subscribe: ['newsletter-2026'],
153
+ checkout: ['buyers-2026'],
154
+ },
155
+ })
156
+ ```
157
+
158
+ Enrollment is silent. There is no checkbox and no label, because the API
159
+ deliberately tells a storefront nothing about a group: an ID naming a list the
160
+ merchant has not opened to public sign-ups is skipped without a word, so a stale
161
+ ID here can never fail somebody's registration or somebody's purchase. At most
162
+ five groups per request are applied, and IDs are matched lowercase.
163
+
164
+ `signUp` and `subscribe` can be added to per link with `mb_groups`:
165
+
166
+ ```html
167
+ <a href="?mb_intent=sign_up&mb_groups=beta,vip">Join the beta</a>
168
+ ```
169
+
170
+ The two are unioned rather than overridden: `configure` names the lists everyone
171
+ signing up through your site joins, the link adds whichever the campaign is for.
172
+ `checkout` is configuration-only, because the cart outlives any one link.
173
+
174
+ For somebody who already has an account, `join_group` does it as a request of its
175
+ own, and unlike the three above it reports whether it worked:
176
+
177
+ ```html
178
+ <a href="?mb_intent=join_group&mb_group_id=beta">Join the beta list</a>
179
+ ```
180
+
181
+ It signs the visitor in first if they aren't, and emits `joined-group` on
182
+ success. Joining a list twice is not an error.
183
+
143
184
  ### Fonts
144
185
 
145
186
  `theme.fonts.heading` and `theme.fonts.body` each take one of:
@@ -312,6 +353,7 @@ Available events include:
312
353
  - `promotion-clicked`
313
354
  - `promotion-dismissed`
314
355
  - `redeemed-voucher`
356
+ - `joined-group`
315
357
  - `downloaded-product`
316
358
  - `activated-product`
317
359
  - `added-to-cart`
@@ -381,7 +423,7 @@ Moonbase.configure({ integrations: { metaPixel: undefined } })
381
423
 
382
424
  ### Data conventions
383
425
 
384
- 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.
426
+ 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-initiated` is the one exception: an order has no settled total until billing details are entered, so its `value` is the cart's own post-discount total and excludes tax. `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.
385
427
 
386
428
  ### Event mapping
387
429
 
@@ -83,6 +83,7 @@ export declare enum MoonbaseEvent {
83
83
  SignedUp = "signed-up",
84
84
  SignedOut = "signed-out",
85
85
  RedeemedVoucher = "redeemed-voucher",
86
+ JoinedGroup = "joined-group",
86
87
  StorefrontUpdated = "storefront-updated",
87
88
  PromotionShown = "promotion-shown",
88
89
  PromotionClicked = "promotion-clicked",
@@ -110,6 +111,11 @@ export declare interface MoonbaseEventArgs {
110
111
  voucher: Voucher;
111
112
  user: User;
112
113
  };
114
+ [MoonbaseEvent.JoinedGroup]: {
115
+ /** The group's ID. The API never tells a storefront a group's name. */
116
+ groupId: string;
117
+ user: User;
118
+ };
113
119
  [MoonbaseEvent.StorefrontUpdated]: {
114
120
  storefront: Storefront;
115
121
  user?: User | null;
@@ -196,6 +202,7 @@ declare class MoonbaseImpl implements MoonbaseInstance {
196
202
  confirm_communication_preferences(parameters?: MoonbaseIntentArgs['confirm_communication_preferences']): void;
197
203
  manage_communication_preferences(parameters?: MoonbaseIntentArgs['manage_communication_preferences']): void;
198
204
  connect_account(parameters?: MoonbaseIntentArgs['connect_account']): void;
205
+ join_group(parameters?: MoonbaseIntentArgs['join_group']): void;
199
206
  view_account(): void;
200
207
  view_products(): void;
201
208
  view_subscriptions(): void;
@@ -238,6 +245,7 @@ export declare enum MoonbaseIntent {
238
245
  ViewSubscriptions = "view_subscriptions",
239
246
  RedeemVoucher = "redeem_voucher",
240
247
  ConnectAccount = "connect_account",
248
+ JoinGroup = "join_group",
241
249
  ViewProduct = "view_product",
242
250
  DownloadProduct = "download_product",
243
251
  ActivateProduct = "activate_product",
@@ -256,6 +264,11 @@ export declare interface MoonbaseIntentArgs {
256
264
  };
257
265
  [MoonbaseIntent.SignUp]: {
258
266
  email?: string;
267
+ /**
268
+ * Comma-separated merchant-owned group IDs to join on sign-up, added to
269
+ * whatever `options.groups.signUp` already names.
270
+ */
271
+ groups?: string;
259
272
  };
260
273
  [MoonbaseIntent.ForgotPassword]: {
261
274
  email?: string;
@@ -278,6 +291,11 @@ export declare interface MoonbaseIntentArgs {
278
291
  };
279
292
  [MoonbaseIntent.Subscribe]: {
280
293
  email?: string;
294
+ /**
295
+ * Comma-separated merchant-owned group IDs to join on subscribe, added to
296
+ * whatever `options.groups.subscribe` already names.
297
+ */
298
+ groups?: string;
281
299
  };
282
300
  [MoonbaseIntent.ConfirmCommunicationPreferences]: {
283
301
  email: string;
@@ -296,6 +314,9 @@ export declare interface MoonbaseIntentArgs {
296
314
  [MoonbaseIntent.ConnectAccount]: {
297
315
  provider_id: string;
298
316
  };
317
+ [MoonbaseIntent.JoinGroup]: {
318
+ group_id: string;
319
+ };
299
320
  [MoonbaseIntent.ViewProduct]: {
300
321
  product_id: string;
301
322
  version?: string;
@@ -368,6 +389,29 @@ export declare interface MoonbaseOptions {
368
389
  productUpdates: boolean;
369
390
  };
370
391
  };
392
+ /**
393
+ * Merchant-owned customer groups a visitor joins when they use one of these
394
+ * forms. Named by ID, because the API deliberately tells a storefront nothing
395
+ * about a group: an ID that names a group the merchant has not opened to
396
+ * public sign-ups is skipped in silence, so a stale one here can never fail a
397
+ * registration or a sale. Enrollment is therefore silent too, and there is
398
+ * nothing to label.
399
+ *
400
+ * `signUp` and `subscribe` can be added to per link with `mb_groups`, e.g.
401
+ * `?mb_intent=sign_up&mb_groups=beta,vip`. The two are unioned: the options
402
+ * say which lists everyone signing up through this site joins, the link adds
403
+ * whichever the campaign is for.
404
+ *
405
+ * `checkout` is options-only. The cart outlives any one intent, and a buyer
406
+ * pressing the drawer's own checkout button never went through a link, so a
407
+ * URL-scoped group there would apply or not depending on which button they
408
+ * happened to press.
409
+ */
410
+ groups: {
411
+ signUp: string[];
412
+ subscribe: string[];
413
+ checkout: string[];
414
+ };
371
415
  checkout: {
372
416
  /**
373
417
  * Where checkout happens.