brainerce 1.37.3 → 1.39.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
@@ -1526,10 +1526,19 @@ fields.forEach((field) => {
1526
1526
  // field.required: whether customer must fill this in
1527
1527
  // field.minLength, field.maxLength: validation for text fields
1528
1528
  // field.minValue, field.maxValue: validation for number fields
1529
- // field.enumValues: allowed options for dropdown fields
1529
+ // field.enumValues: CustomizationFieldOption[] for SELECT/MULTI_SELECT
1530
+ // each option: { label: string, value: string, swatchColor?: string, swatchImageUrl?: string }
1531
+ // use option.value for metadata submission, option.label for display
1530
1532
  // field.defaultValue: default value to pre-fill
1531
1533
  });
1532
1534
 
1535
+ // Render SELECT options using label/value (not string[] anymore):
1536
+ for (const option of field.enumValues ?? []) {
1537
+ // option.label → show to user (e.g. "Gold")
1538
+ // option.value → submit in metadata (e.g. "gold")
1539
+ // option.swatchColor → hex color for color swatch UI, if set
1540
+ }
1541
+
1533
1542
  // Customer fills in values, then add to cart with metadata
1534
1543
  await client.addToCart(cartId, {
1535
1544
  productId: product.id,
@@ -1537,10 +1546,23 @@ await client.addToCart(cartId, {
1537
1546
  metadata: {
1538
1547
  cake_text: 'Happy Birthday!', // TEXT field
1539
1548
  font_color: '#FF0000', // COLOR field
1549
+ frame_color: 'gold', // SELECT — use option.value
1540
1550
  },
1541
1551
  });
1542
1552
  ```
1543
1553
 
1554
+ **Display customizations in cart/checkout — no extra API call needed:**
1555
+
1556
+ `CartItem` and `CheckoutLineItem` both include a `customizations` object with resolved labels. Use it directly — no need to call `getProduct()` per item.
1557
+
1558
+ ```typescript
1559
+ // Works for CartItem, CheckoutLineItem, and OrderItem — same shape
1560
+ const summary = Object.values(item.customizations ?? {})
1561
+ .map(c => `${c.label}: ${Array.isArray(c.value) ? c.value.join(', ') : c.value}`)
1562
+ .join(' | ');
1563
+ // e.g. "Frame color: Gold | Add-ons: Gift wrap, Engraving"
1564
+ ```
1565
+
1544
1566
  **For IMAGE/GALLERY fields**, upload the file first:
1545
1567
 
1546
1568
  ```typescript
@@ -3361,6 +3383,51 @@ console.log(store.language); // 'en', 'he', etc.
3361
3383
 
3362
3384
  ---
3363
3385
 
3386
+ ### Traffic Analytics (built-in, no GA4 needed)
3387
+
3388
+ Brainerce has a **native cookieless analytics pipeline** — visits, visitors, countries, sources, devices, conversion funnel — visible in the merchant dashboard under **Dashboard → Traffic**. You don't need GA4, Meta Pixel, or any third-party script.
3389
+
3390
+ **Option A — Script tag (recommended, zero JS):**
3391
+
3392
+ Add one line to your root layout `<head>`:
3393
+
3394
+ ```html
3395
+ <!-- Vibe-coded (salesChannelId) mode -->
3396
+ <script defer src="https://api.brainerce.com/t.js" data-channel="vc_abc123"></script>
3397
+
3398
+ <!-- storeId mode -->
3399
+ <script defer src="https://api.brainerce.com/t.js" data-store-id="your_store_id"></script>
3400
+ ```
3401
+
3402
+ The pixel auto-tracks pageviews on load and on every SPA route change, de-dupes consecutive identical paths, and measures active dwell time. Scaffolds from `create-brainerce-store ≥ 1.50` include it automatically.
3403
+
3404
+ **Option B — SDK method (JS import, same endpoint):**
3405
+
3406
+ ```typescript
3407
+ // Basic pageview — call this on route changes if you're not using t.js
3408
+ client.trackEvent({ eventType: 'pageview', path: '/products/shoes' });
3409
+
3410
+ // With UTM attribution (from URL params)
3411
+ const params = new URLSearchParams(window.location.search);
3412
+ client.trackEvent({
3413
+ path: window.location.pathname,
3414
+ utmSource: params.get('utm_source') ?? undefined,
3415
+ utmMedium: params.get('utm_medium') ?? undefined,
3416
+ utmCampaign: params.get('utm_campaign') ?? undefined,
3417
+ screenWidth: window.innerWidth,
3418
+ lang: navigator.language,
3419
+ });
3420
+
3421
+ // Engagement dwell time (send on route change or pagehide)
3422
+ client.trackEvent({ eventType: 'engagement', path: '/products/shoes', engagedMs: 12000 });
3423
+ ```
3424
+
3425
+ > `trackEvent()` is fire-and-forget — errors are silently swallowed so a failed beacon never breaks your storefront. Available in `salesChannelId` and `storeId` modes.
3426
+
3427
+ **Privacy:** cookieless, no PII stored. The visitor IP is resolved to a country server-side and then discarded. No cookie-consent banner required under GDPR/ePrivacy.
3428
+
3429
+ ---
3430
+
3364
3431
  ## Admin API Reference
3365
3432
 
3366
3433
  > ⛔ **Server-side only.** The `apiKey` (`brainerce_*`) is a privileged secret — NEVER put it in browser code, client bundles, or any code that ships to the user's machine. It belongs in an environment variable on your server. For building the customer-facing storefront, use `salesChannelId` instead (see [Quick Start](#quick-start)).
@@ -3505,6 +3572,26 @@ await client.createZoneShippingRate('zone_id', {
3505
3572
  });
3506
3573
  ```
3507
3574
 
3575
+ ### App Store Shipping (Shippo)
3576
+
3577
+ Once a merchant installs the Shippo app from the Brainerce App Store and connects their own
3578
+ Shippo account, live carrier rates appear automatically at checkout. Billing goes directly
3579
+ to the merchant's Shippo account.
3580
+
3581
+ ```typescript
3582
+ // After an order is placed, purchase a shipping label:
3583
+ const label = await admin.createShippingLabel(orderId, {
3584
+ shippoRateObjectId: 'rate_8f123456789abcdef', // Shippo rate.object_id from checkout rates
3585
+ });
3586
+
3587
+ console.log(label.labelUrl); // PDF label URL for printing
3588
+ console.log(label.trackingNumber); // Auto-populated on the order
3589
+ console.log(label.carrier); // e.g. 'USPS', 'UPS', 'FedEx'
3590
+ ```
3591
+
3592
+ The `trackingNumber` is stored on the `Order` automatically — customers see it in their
3593
+ order history without any extra integration work.
3594
+
3508
3595
  ### Tax Configuration
3509
3596
 
3510
3597
  `rate` is a **whole percentage** (`7.25` = 7.25%, not `0.0725`). A rate may target
package/dist/index.d.mts CHANGED
@@ -1806,6 +1806,20 @@ interface CartItem {
1806
1806
  notes?: string | null;
1807
1807
  /** Optional metadata for this line item */
1808
1808
  metadata?: Record<string, unknown> | null;
1809
+ /**
1810
+ * Resolved customer input field values with merchant-defined labels.
1811
+ * Mirrors `OrderItem.customizations` — same shape, live (not order-frozen).
1812
+ * Present only when the item has at least one customization value set.
1813
+ *
1814
+ * @example
1815
+ * // Display "Color: Silver / Size: 45" without an extra getProduct() call:
1816
+ * Object.entries(item.customizations ?? {}).map(([, c]) => `${c.label}: ${c.value}`)
1817
+ */
1818
+ customizations?: Record<string, {
1819
+ label: string;
1820
+ value: string | string[];
1821
+ type: string;
1822
+ }>;
1809
1823
  /**
1810
1824
  * Per-line modifier breakdown — present when the line was added with
1811
1825
  * modifier `selections`. Snapshot taken at add-time; immutable to catalog
@@ -2326,6 +2340,20 @@ interface CheckoutLineItem {
2326
2340
  notes?: string | null;
2327
2341
  /** Custom metadata including customer input field values */
2328
2342
  metadata?: Record<string, unknown> | null;
2343
+ /**
2344
+ * Resolved customer input field values with merchant-defined labels.
2345
+ * Mirrors `OrderItem.customizations` — same shape, live (not order-frozen).
2346
+ * Present only when the item has at least one customization value set.
2347
+ *
2348
+ * @example
2349
+ * // Render "Color: Silver / Ring size: 45" in your checkout summary:
2350
+ * Object.entries(item.customizations ?? {}).map(([, c]) => `${c.label}: ${c.value}`)
2351
+ */
2352
+ customizations?: Record<string, {
2353
+ label: string;
2354
+ value: string | string[];
2355
+ type: string;
2356
+ }>;
2329
2357
  }
2330
2358
  /**
2331
2359
  * Represents an available shipping rate/method for checkout.
@@ -3983,7 +4011,8 @@ interface MetafieldDefinition {
3983
4011
  maxLength?: number | null;
3984
4012
  minValue?: number | null;
3985
4013
  maxValue?: number | null;
3986
- enumValues?: string[] | null;
4014
+ /** Allowed values for SELECT / MULTI_SELECT fields, with optional swatch metadata. */
4015
+ enumValues?: CustomizationFieldOption[] | null;
3987
4016
  defaultValue?: string | null;
3988
4017
  position: number;
3989
4018
  isActive: boolean;
@@ -4067,7 +4096,8 @@ interface PublicMetafieldDefinition {
4067
4096
  * Pair with `getProducts({ metafields: { [key]: [...] } })`.
4068
4097
  */
4069
4098
  filterable?: boolean;
4070
- enumValues?: string[];
4099
+ /** Allowed values for SELECT / MULTI_SELECT fields, with optional swatch metadata. */
4100
+ enumValues?: CustomizationFieldOption[];
4071
4101
  minLength?: number | null;
4072
4102
  maxLength?: number | null;
4073
4103
  minValue?: number | null;
@@ -4075,6 +4105,20 @@ interface PublicMetafieldDefinition {
4075
4105
  defaultValue?: string | null;
4076
4106
  position: number;
4077
4107
  }
4108
+ /**
4109
+ * A single selectable option for a SELECT or MULTI_SELECT customization field.
4110
+ * Legacy string-only `enumValues` arrays are automatically promoted to this shape.
4111
+ */
4112
+ interface CustomizationFieldOption {
4113
+ /** Human-readable label shown in the storefront UI (e.g., "Rose Gold"). */
4114
+ label: string;
4115
+ /** Value stored in `CartItem.metadata` and carried through to `OrderItem.customizations`. */
4116
+ value: string;
4117
+ /** Optional CSS hex color for rendering a color swatch (e.g., "#B76E79"). */
4118
+ swatchColor?: string | null;
4119
+ /** Optional image URL for rendering a texture/image swatch. */
4120
+ swatchImageUrl?: string | null;
4121
+ }
4078
4122
  /**
4079
4123
  * Customer-facing input field definition assigned to a specific product.
4080
4124
  * Returned in product responses to tell the storefront which input fields to render.
@@ -4090,7 +4134,11 @@ interface ProductCustomizationField {
4090
4134
  maxLength?: number | null;
4091
4135
  minValue?: number | null;
4092
4136
  maxValue?: number | null;
4093
- enumValues?: string[];
4137
+ /**
4138
+ * Allowed values for SELECT / MULTI_SELECT fields.
4139
+ * Each option includes a label, value, and optional swatch color/image.
4140
+ */
4141
+ enumValues?: CustomizationFieldOption[];
4094
4142
  defaultValue?: string | null;
4095
4143
  position: number;
4096
4144
  }
@@ -5306,6 +5354,30 @@ interface BlogPostListResponse {
5306
5354
  totalPages: number;
5307
5355
  };
5308
5356
  }
5357
+ /**
5358
+ * Payload for `client.trackEvent()` — the programmatic counterpart to the
5359
+ * `t.js` script-tag pixel. Every field is optional; the server degrades
5360
+ * gracefully on missing values. Deliberately collects no PII: `path` is
5361
+ * pathname-only, `referrer` is reduced to a hostname server-side, and the
5362
+ * visitor IP is resolved to a country then discarded.
5363
+ */
5364
+ interface TrackEventPayload {
5365
+ /** `'pageview'` (default) or `'engagement'` (active dwell-time report). */
5366
+ eventType?: 'pageview' | 'engagement';
5367
+ /** `window.location.pathname` — no query string (intentional, avoids PII). */
5368
+ path?: string;
5369
+ /** `document.referrer` — full URL, reduced to hostname server-side. */
5370
+ referrer?: string;
5371
+ utmSource?: string;
5372
+ utmMedium?: string;
5373
+ utmCampaign?: string;
5374
+ /** Viewport width in px — used for mobile/tablet/desktop classification. */
5375
+ screenWidth?: number;
5376
+ /** `navigator.language` — coarse locale hint for future breakdowns. */
5377
+ lang?: string;
5378
+ /** Active dwell time in ms. Only meaningful for `eventType: 'engagement'`. Max 1 800 000 (30 min). */
5379
+ engagedMs?: number;
5380
+ }
5309
5381
  interface BrainerceApiError {
5310
5382
  statusCode: number;
5311
5383
  message: string;
@@ -5491,6 +5563,39 @@ declare class BrainerceClient {
5491
5563
  * `'ltr'` for everything else (including unknown locales).
5492
5564
  */
5493
5565
  getStoreDirection(locale?: string | null): 'ltr' | 'rtl';
5566
+ /**
5567
+ * Send a storefront analytics beacon (pageview or engagement).
5568
+ *
5569
+ * This is the programmatic counterpart to the `t.js` script-tag pixel —
5570
+ * use it when you prefer a JS import over a `<script>` tag, or when you
5571
+ * need to fire events the auto-tracker doesn't cover.
5572
+ *
5573
+ * **If you're already loading `t.js`, you do NOT need this** — the pixel
5574
+ * handles pageviews and SPA route changes automatically.
5575
+ *
5576
+ * The call is fire-and-forget: errors are swallowed so a failed beacon
5577
+ * never breaks your storefront. Available in `salesChannelId` and `storeId`
5578
+ * modes; silently skipped in admin mode (server-to-server beacons are
5579
+ * meaningless without a real browser session).
5580
+ *
5581
+ * @example
5582
+ * ```typescript
5583
+ * // Basic pageview (equivalent to what t.js sends automatically)
5584
+ * client.trackEvent({ eventType: 'pageview', path: '/products/shoes' });
5585
+ *
5586
+ * // With UTM attribution
5587
+ * client.trackEvent({
5588
+ * path: '/products/shoes',
5589
+ * utmSource: 'newsletter',
5590
+ * utmMedium: 'email',
5591
+ * utmCampaign: 'summer-sale',
5592
+ * });
5593
+ *
5594
+ * // Engagement (active dwell time in ms — send on route change or pagehide)
5595
+ * client.trackEvent({ eventType: 'engagement', path: '/products/shoes', engagedMs: 12000 });
5596
+ * ```
5597
+ */
5598
+ trackEvent(payload?: TrackEventPayload): Promise<void>;
5494
5599
  /**
5495
5600
  * Get a list of products with pagination and filtering
5496
5601
  * Works in vibe-coded, storefront (public), and admin mode
@@ -5915,6 +6020,29 @@ declare class BrainerceClient {
5915
6020
  * ```
5916
6021
  */
5917
6022
  updateOrderShipping(orderId: string, data: UpdateOrderShippingDto): Promise<Order>;
6023
+ /**
6024
+ * Create a shipping label for an order via the installed App Store shipping app.
6025
+ * Pass the rate ID returned from checkout rate shopping. Billing goes directly
6026
+ * to the merchant's carrier account — Brainerce is not a billing intermediary.
6027
+ *
6028
+ * @example
6029
+ * ```typescript
6030
+ * const label = await client.createShippingLabel('order_abc', {
6031
+ * rateId: 'rate_8f123456789abcdef',
6032
+ * });
6033
+ * console.log('Label URL:', label.labelUrl);
6034
+ * console.log('Tracking:', label.trackingNumber);
6035
+ * ```
6036
+ */
6037
+ createShippingLabel(orderId: string, data: {
6038
+ rateId: string;
6039
+ parcel?: Record<string, string>;
6040
+ }): Promise<{
6041
+ shipmentId: string;
6042
+ labelUrl: string;
6043
+ trackingNumber: string;
6044
+ carrier: string;
6045
+ }>;
5918
6046
  /**
5919
6047
  * Cancel an order
5920
6048
  * Works for Shopify and WooCommerce orders that haven't been fulfilled
package/dist/index.d.ts CHANGED
@@ -1806,6 +1806,20 @@ interface CartItem {
1806
1806
  notes?: string | null;
1807
1807
  /** Optional metadata for this line item */
1808
1808
  metadata?: Record<string, unknown> | null;
1809
+ /**
1810
+ * Resolved customer input field values with merchant-defined labels.
1811
+ * Mirrors `OrderItem.customizations` — same shape, live (not order-frozen).
1812
+ * Present only when the item has at least one customization value set.
1813
+ *
1814
+ * @example
1815
+ * // Display "Color: Silver / Size: 45" without an extra getProduct() call:
1816
+ * Object.entries(item.customizations ?? {}).map(([, c]) => `${c.label}: ${c.value}`)
1817
+ */
1818
+ customizations?: Record<string, {
1819
+ label: string;
1820
+ value: string | string[];
1821
+ type: string;
1822
+ }>;
1809
1823
  /**
1810
1824
  * Per-line modifier breakdown — present when the line was added with
1811
1825
  * modifier `selections`. Snapshot taken at add-time; immutable to catalog
@@ -2326,6 +2340,20 @@ interface CheckoutLineItem {
2326
2340
  notes?: string | null;
2327
2341
  /** Custom metadata including customer input field values */
2328
2342
  metadata?: Record<string, unknown> | null;
2343
+ /**
2344
+ * Resolved customer input field values with merchant-defined labels.
2345
+ * Mirrors `OrderItem.customizations` — same shape, live (not order-frozen).
2346
+ * Present only when the item has at least one customization value set.
2347
+ *
2348
+ * @example
2349
+ * // Render "Color: Silver / Ring size: 45" in your checkout summary:
2350
+ * Object.entries(item.customizations ?? {}).map(([, c]) => `${c.label}: ${c.value}`)
2351
+ */
2352
+ customizations?: Record<string, {
2353
+ label: string;
2354
+ value: string | string[];
2355
+ type: string;
2356
+ }>;
2329
2357
  }
2330
2358
  /**
2331
2359
  * Represents an available shipping rate/method for checkout.
@@ -3983,7 +4011,8 @@ interface MetafieldDefinition {
3983
4011
  maxLength?: number | null;
3984
4012
  minValue?: number | null;
3985
4013
  maxValue?: number | null;
3986
- enumValues?: string[] | null;
4014
+ /** Allowed values for SELECT / MULTI_SELECT fields, with optional swatch metadata. */
4015
+ enumValues?: CustomizationFieldOption[] | null;
3987
4016
  defaultValue?: string | null;
3988
4017
  position: number;
3989
4018
  isActive: boolean;
@@ -4067,7 +4096,8 @@ interface PublicMetafieldDefinition {
4067
4096
  * Pair with `getProducts({ metafields: { [key]: [...] } })`.
4068
4097
  */
4069
4098
  filterable?: boolean;
4070
- enumValues?: string[];
4099
+ /** Allowed values for SELECT / MULTI_SELECT fields, with optional swatch metadata. */
4100
+ enumValues?: CustomizationFieldOption[];
4071
4101
  minLength?: number | null;
4072
4102
  maxLength?: number | null;
4073
4103
  minValue?: number | null;
@@ -4075,6 +4105,20 @@ interface PublicMetafieldDefinition {
4075
4105
  defaultValue?: string | null;
4076
4106
  position: number;
4077
4107
  }
4108
+ /**
4109
+ * A single selectable option for a SELECT or MULTI_SELECT customization field.
4110
+ * Legacy string-only `enumValues` arrays are automatically promoted to this shape.
4111
+ */
4112
+ interface CustomizationFieldOption {
4113
+ /** Human-readable label shown in the storefront UI (e.g., "Rose Gold"). */
4114
+ label: string;
4115
+ /** Value stored in `CartItem.metadata` and carried through to `OrderItem.customizations`. */
4116
+ value: string;
4117
+ /** Optional CSS hex color for rendering a color swatch (e.g., "#B76E79"). */
4118
+ swatchColor?: string | null;
4119
+ /** Optional image URL for rendering a texture/image swatch. */
4120
+ swatchImageUrl?: string | null;
4121
+ }
4078
4122
  /**
4079
4123
  * Customer-facing input field definition assigned to a specific product.
4080
4124
  * Returned in product responses to tell the storefront which input fields to render.
@@ -4090,7 +4134,11 @@ interface ProductCustomizationField {
4090
4134
  maxLength?: number | null;
4091
4135
  minValue?: number | null;
4092
4136
  maxValue?: number | null;
4093
- enumValues?: string[];
4137
+ /**
4138
+ * Allowed values for SELECT / MULTI_SELECT fields.
4139
+ * Each option includes a label, value, and optional swatch color/image.
4140
+ */
4141
+ enumValues?: CustomizationFieldOption[];
4094
4142
  defaultValue?: string | null;
4095
4143
  position: number;
4096
4144
  }
@@ -5306,6 +5354,30 @@ interface BlogPostListResponse {
5306
5354
  totalPages: number;
5307
5355
  };
5308
5356
  }
5357
+ /**
5358
+ * Payload for `client.trackEvent()` — the programmatic counterpart to the
5359
+ * `t.js` script-tag pixel. Every field is optional; the server degrades
5360
+ * gracefully on missing values. Deliberately collects no PII: `path` is
5361
+ * pathname-only, `referrer` is reduced to a hostname server-side, and the
5362
+ * visitor IP is resolved to a country then discarded.
5363
+ */
5364
+ interface TrackEventPayload {
5365
+ /** `'pageview'` (default) or `'engagement'` (active dwell-time report). */
5366
+ eventType?: 'pageview' | 'engagement';
5367
+ /** `window.location.pathname` — no query string (intentional, avoids PII). */
5368
+ path?: string;
5369
+ /** `document.referrer` — full URL, reduced to hostname server-side. */
5370
+ referrer?: string;
5371
+ utmSource?: string;
5372
+ utmMedium?: string;
5373
+ utmCampaign?: string;
5374
+ /** Viewport width in px — used for mobile/tablet/desktop classification. */
5375
+ screenWidth?: number;
5376
+ /** `navigator.language` — coarse locale hint for future breakdowns. */
5377
+ lang?: string;
5378
+ /** Active dwell time in ms. Only meaningful for `eventType: 'engagement'`. Max 1 800 000 (30 min). */
5379
+ engagedMs?: number;
5380
+ }
5309
5381
  interface BrainerceApiError {
5310
5382
  statusCode: number;
5311
5383
  message: string;
@@ -5491,6 +5563,39 @@ declare class BrainerceClient {
5491
5563
  * `'ltr'` for everything else (including unknown locales).
5492
5564
  */
5493
5565
  getStoreDirection(locale?: string | null): 'ltr' | 'rtl';
5566
+ /**
5567
+ * Send a storefront analytics beacon (pageview or engagement).
5568
+ *
5569
+ * This is the programmatic counterpart to the `t.js` script-tag pixel —
5570
+ * use it when you prefer a JS import over a `<script>` tag, or when you
5571
+ * need to fire events the auto-tracker doesn't cover.
5572
+ *
5573
+ * **If you're already loading `t.js`, you do NOT need this** — the pixel
5574
+ * handles pageviews and SPA route changes automatically.
5575
+ *
5576
+ * The call is fire-and-forget: errors are swallowed so a failed beacon
5577
+ * never breaks your storefront. Available in `salesChannelId` and `storeId`
5578
+ * modes; silently skipped in admin mode (server-to-server beacons are
5579
+ * meaningless without a real browser session).
5580
+ *
5581
+ * @example
5582
+ * ```typescript
5583
+ * // Basic pageview (equivalent to what t.js sends automatically)
5584
+ * client.trackEvent({ eventType: 'pageview', path: '/products/shoes' });
5585
+ *
5586
+ * // With UTM attribution
5587
+ * client.trackEvent({
5588
+ * path: '/products/shoes',
5589
+ * utmSource: 'newsletter',
5590
+ * utmMedium: 'email',
5591
+ * utmCampaign: 'summer-sale',
5592
+ * });
5593
+ *
5594
+ * // Engagement (active dwell time in ms — send on route change or pagehide)
5595
+ * client.trackEvent({ eventType: 'engagement', path: '/products/shoes', engagedMs: 12000 });
5596
+ * ```
5597
+ */
5598
+ trackEvent(payload?: TrackEventPayload): Promise<void>;
5494
5599
  /**
5495
5600
  * Get a list of products with pagination and filtering
5496
5601
  * Works in vibe-coded, storefront (public), and admin mode
@@ -5915,6 +6020,29 @@ declare class BrainerceClient {
5915
6020
  * ```
5916
6021
  */
5917
6022
  updateOrderShipping(orderId: string, data: UpdateOrderShippingDto): Promise<Order>;
6023
+ /**
6024
+ * Create a shipping label for an order via the installed App Store shipping app.
6025
+ * Pass the rate ID returned from checkout rate shopping. Billing goes directly
6026
+ * to the merchant's carrier account — Brainerce is not a billing intermediary.
6027
+ *
6028
+ * @example
6029
+ * ```typescript
6030
+ * const label = await client.createShippingLabel('order_abc', {
6031
+ * rateId: 'rate_8f123456789abcdef',
6032
+ * });
6033
+ * console.log('Label URL:', label.labelUrl);
6034
+ * console.log('Tracking:', label.trackingNumber);
6035
+ * ```
6036
+ */
6037
+ createShippingLabel(orderId: string, data: {
6038
+ rateId: string;
6039
+ parcel?: Record<string, string>;
6040
+ }): Promise<{
6041
+ shipmentId: string;
6042
+ labelUrl: string;
6043
+ trackingNumber: string;
6044
+ carrier: string;
6045
+ }>;
5918
6046
  /**
5919
6047
  * Cancel an order
5920
6048
  * Works for Shopify and WooCommerce orders that haven't been fulfilled
package/dist/index.js CHANGED
@@ -1072,6 +1072,49 @@ var BrainerceClient = class {
1072
1072
  getStoreDirection(locale) {
1073
1073
  return getDirectionForLocale(locale ?? this.locale);
1074
1074
  }
1075
+ // -------------------- Analytics --------------------
1076
+ /**
1077
+ * Send a storefront analytics beacon (pageview or engagement).
1078
+ *
1079
+ * This is the programmatic counterpart to the `t.js` script-tag pixel —
1080
+ * use it when you prefer a JS import over a `<script>` tag, or when you
1081
+ * need to fire events the auto-tracker doesn't cover.
1082
+ *
1083
+ * **If you're already loading `t.js`, you do NOT need this** — the pixel
1084
+ * handles pageviews and SPA route changes automatically.
1085
+ *
1086
+ * The call is fire-and-forget: errors are swallowed so a failed beacon
1087
+ * never breaks your storefront. Available in `salesChannelId` and `storeId`
1088
+ * modes; silently skipped in admin mode (server-to-server beacons are
1089
+ * meaningless without a real browser session).
1090
+ *
1091
+ * @example
1092
+ * ```typescript
1093
+ * // Basic pageview (equivalent to what t.js sends automatically)
1094
+ * client.trackEvent({ eventType: 'pageview', path: '/products/shoes' });
1095
+ *
1096
+ * // With UTM attribution
1097
+ * client.trackEvent({
1098
+ * path: '/products/shoes',
1099
+ * utmSource: 'newsletter',
1100
+ * utmMedium: 'email',
1101
+ * utmCampaign: 'summer-sale',
1102
+ * });
1103
+ *
1104
+ * // Engagement (active dwell time in ms — send on route change or pagehide)
1105
+ * client.trackEvent({ eventType: 'engagement', path: '/products/shoes', engagedMs: 12000 });
1106
+ * ```
1107
+ */
1108
+ async trackEvent(payload = {}) {
1109
+ try {
1110
+ if (this.isVibeCodedMode()) {
1111
+ await this.vibeCodedRequest("POST", "/events", payload);
1112
+ } else if (this.isStorefrontMode()) {
1113
+ await this.storefrontRequest("POST", "/events", payload);
1114
+ }
1115
+ } catch {
1116
+ }
1117
+ }
1075
1118
  // -------------------- Products --------------------
1076
1119
  /**
1077
1120
  * Get a list of products with pagination and filtering
@@ -1762,6 +1805,27 @@ var BrainerceClient = class {
1762
1805
  data
1763
1806
  );
1764
1807
  }
1808
+ /**
1809
+ * Create a shipping label for an order via the installed App Store shipping app.
1810
+ * Pass the rate ID returned from checkout rate shopping. Billing goes directly
1811
+ * to the merchant's carrier account — Brainerce is not a billing intermediary.
1812
+ *
1813
+ * @example
1814
+ * ```typescript
1815
+ * const label = await client.createShippingLabel('order_abc', {
1816
+ * rateId: 'rate_8f123456789abcdef',
1817
+ * });
1818
+ * console.log('Label URL:', label.labelUrl);
1819
+ * console.log('Tracking:', label.trackingNumber);
1820
+ * ```
1821
+ */
1822
+ async createShippingLabel(orderId, data) {
1823
+ return this.request(
1824
+ "POST",
1825
+ `/api/v1/orders/${encodePathSegment(orderId)}/shipments/app-label`,
1826
+ data
1827
+ );
1828
+ }
1765
1829
  /**
1766
1830
  * Cancel an order
1767
1831
  * Works for Shopify and WooCommerce orders that haven't been fulfilled
package/dist/index.mjs CHANGED
@@ -1002,6 +1002,49 @@ var BrainerceClient = class {
1002
1002
  getStoreDirection(locale) {
1003
1003
  return getDirectionForLocale(locale ?? this.locale);
1004
1004
  }
1005
+ // -------------------- Analytics --------------------
1006
+ /**
1007
+ * Send a storefront analytics beacon (pageview or engagement).
1008
+ *
1009
+ * This is the programmatic counterpart to the `t.js` script-tag pixel —
1010
+ * use it when you prefer a JS import over a `<script>` tag, or when you
1011
+ * need to fire events the auto-tracker doesn't cover.
1012
+ *
1013
+ * **If you're already loading `t.js`, you do NOT need this** — the pixel
1014
+ * handles pageviews and SPA route changes automatically.
1015
+ *
1016
+ * The call is fire-and-forget: errors are swallowed so a failed beacon
1017
+ * never breaks your storefront. Available in `salesChannelId` and `storeId`
1018
+ * modes; silently skipped in admin mode (server-to-server beacons are
1019
+ * meaningless without a real browser session).
1020
+ *
1021
+ * @example
1022
+ * ```typescript
1023
+ * // Basic pageview (equivalent to what t.js sends automatically)
1024
+ * client.trackEvent({ eventType: 'pageview', path: '/products/shoes' });
1025
+ *
1026
+ * // With UTM attribution
1027
+ * client.trackEvent({
1028
+ * path: '/products/shoes',
1029
+ * utmSource: 'newsletter',
1030
+ * utmMedium: 'email',
1031
+ * utmCampaign: 'summer-sale',
1032
+ * });
1033
+ *
1034
+ * // Engagement (active dwell time in ms — send on route change or pagehide)
1035
+ * client.trackEvent({ eventType: 'engagement', path: '/products/shoes', engagedMs: 12000 });
1036
+ * ```
1037
+ */
1038
+ async trackEvent(payload = {}) {
1039
+ try {
1040
+ if (this.isVibeCodedMode()) {
1041
+ await this.vibeCodedRequest("POST", "/events", payload);
1042
+ } else if (this.isStorefrontMode()) {
1043
+ await this.storefrontRequest("POST", "/events", payload);
1044
+ }
1045
+ } catch {
1046
+ }
1047
+ }
1005
1048
  // -------------------- Products --------------------
1006
1049
  /**
1007
1050
  * Get a list of products with pagination and filtering
@@ -1692,6 +1735,27 @@ var BrainerceClient = class {
1692
1735
  data
1693
1736
  );
1694
1737
  }
1738
+ /**
1739
+ * Create a shipping label for an order via the installed App Store shipping app.
1740
+ * Pass the rate ID returned from checkout rate shopping. Billing goes directly
1741
+ * to the merchant's carrier account — Brainerce is not a billing intermediary.
1742
+ *
1743
+ * @example
1744
+ * ```typescript
1745
+ * const label = await client.createShippingLabel('order_abc', {
1746
+ * rateId: 'rate_8f123456789abcdef',
1747
+ * });
1748
+ * console.log('Label URL:', label.labelUrl);
1749
+ * console.log('Tracking:', label.trackingNumber);
1750
+ * ```
1751
+ */
1752
+ async createShippingLabel(orderId, data) {
1753
+ return this.request(
1754
+ "POST",
1755
+ `/api/v1/orders/${encodePathSegment(orderId)}/shipments/app-label`,
1756
+ data
1757
+ );
1758
+ }
1695
1759
  /**
1696
1760
  * Cancel an order
1697
1761
  * Works for Shopify and WooCommerce orders that haven't been fulfilled
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainerce",
3
- "version": "1.37.3",
3
+ "version": "1.39.0",
4
4
  "description": "Official SDK for building e-commerce storefronts with Brainerce Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",