@proxima-io/storefront-core 0.3.0 → 0.8.1
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 +23 -17
- package/dist/addresses/address-book.d.ts +36 -0
- package/dist/addresses/address-book.d.ts.map +1 -0
- package/dist/addresses/address-book.js +62 -0
- package/dist/addresses/address-book.js.map +1 -0
- package/dist/analytics/analytics.d.ts +28 -0
- package/dist/analytics/analytics.d.ts.map +1 -0
- package/dist/analytics/analytics.js +124 -0
- package/dist/analytics/analytics.js.map +1 -0
- package/dist/analytics/attribution.d.ts +28 -0
- package/dist/analytics/attribution.d.ts.map +1 -0
- package/dist/analytics/attribution.js +116 -0
- package/dist/analytics/attribution.js.map +1 -0
- package/dist/analytics/session.d.ts +12 -0
- package/dist/analytics/session.d.ts.map +1 -0
- package/dist/analytics/session.js +62 -0
- package/dist/analytics/session.js.map +1 -0
- package/dist/analytics/trackers.d.ts +29 -0
- package/dist/analytics/trackers.d.ts.map +1 -0
- package/dist/analytics/trackers.js +30 -0
- package/dist/analytics/trackers.js.map +1 -0
- package/dist/api/endpoints.d.ts +70 -0
- package/dist/api/endpoints.d.ts.map +1 -0
- package/dist/api/endpoints.js +70 -0
- package/dist/api/endpoints.js.map +1 -0
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +3 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/storefront-client.d.ts +50 -0
- package/dist/api/storefront-client.d.ts.map +1 -0
- package/dist/api/storefront-client.js +123 -0
- package/dist/api/storefront-client.js.map +1 -0
- package/dist/buyer/auth.d.ts +105 -0
- package/dist/buyer/auth.d.ts.map +1 -0
- package/dist/buyer/auth.js +215 -0
- package/dist/buyer/auth.js.map +1 -0
- package/dist/cache/cache.d.ts +31 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +71 -0
- package/dist/cache/cache.js.map +1 -0
- package/dist/campaign/countdown.d.ts +40 -0
- package/dist/campaign/countdown.d.ts.map +1 -0
- package/dist/campaign/countdown.js +71 -0
- package/dist/campaign/countdown.js.map +1 -0
- package/dist/cart/cart.d.ts +57 -0
- package/dist/cart/cart.d.ts.map +1 -0
- package/dist/cart/cart.js +64 -0
- package/dist/cart/cart.js.map +1 -0
- package/dist/catalog/listings.d.ts +87 -0
- package/dist/catalog/listings.d.ts.map +1 -0
- package/dist/catalog/listings.js +140 -0
- package/dist/catalog/listings.js.map +1 -0
- package/dist/cms/payment-methods.d.ts +13 -0
- package/dist/cms/payment-methods.d.ts.map +1 -0
- package/dist/cms/payment-methods.js +41 -0
- package/dist/cms/payment-methods.js.map +1 -0
- package/dist/cms/website.d.ts +74 -0
- package/dist/cms/website.d.ts.map +1 -0
- package/dist/cms/website.js +144 -0
- package/dist/cms/website.js.map +1 -0
- package/dist/cookie-consent/consent.d.ts +22 -0
- package/dist/cookie-consent/consent.d.ts.map +1 -0
- package/dist/cookie-consent/consent.js +93 -0
- package/dist/cookie-consent/consent.js.map +1 -0
- package/dist/index.d.ts +43 -1310
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -1576
- package/dist/index.js.map +1 -1
- package/dist/internal/http.d.ts +5 -0
- package/dist/internal/http.d.ts.map +1 -0
- package/dist/internal/http.js +27 -0
- package/dist/internal/http.js.map +1 -0
- package/dist/orders/guest.d.ts +9 -0
- package/dist/orders/guest.d.ts.map +1 -0
- package/dist/orders/guest.js +30 -0
- package/dist/orders/guest.js.map +1 -0
- package/dist/orders/orders.d.ts +23 -0
- package/dist/orders/orders.d.ts.map +1 -0
- package/dist/orders/orders.js +33 -0
- package/dist/orders/orders.js.map +1 -0
- package/dist/seo/indexnow.d.ts +24 -0
- package/dist/seo/indexnow.d.ts.map +1 -0
- package/dist/seo/indexnow.js +50 -0
- package/dist/seo/indexnow.js.map +1 -0
- package/dist/seo/json-ld.d.ts +52 -0
- package/dist/seo/json-ld.d.ts.map +1 -0
- package/dist/seo/json-ld.js +175 -0
- package/dist/seo/json-ld.js.map +1 -0
- package/dist/seo/page-seo.d.ts +21 -0
- package/dist/seo/page-seo.d.ts.map +1 -0
- package/dist/seo/page-seo.js +68 -0
- package/dist/seo/page-seo.js.map +1 -0
- package/dist/seo/robots.d.ts +23 -0
- package/dist/seo/robots.d.ts.map +1 -0
- package/dist/seo/robots.js +35 -0
- package/dist/seo/robots.js.map +1 -0
- package/dist/seo/sitemap.d.ts +35 -0
- package/dist/seo/sitemap.d.ts.map +1 -0
- package/dist/seo/sitemap.js +131 -0
- package/dist/seo/sitemap.js.map +1 -0
- package/dist/server/process.d.ts +136 -0
- package/dist/server/process.d.ts.map +1 -0
- package/dist/server/process.js +143 -0
- package/dist/server/process.js.map +1 -0
- package/dist/types/address.d.ts +40 -0
- package/dist/types/address.d.ts.map +1 -0
- package/dist/types/address.js +2 -0
- package/dist/types/address.js.map +1 -0
- package/dist/types/analytics.d.ts +79 -0
- package/dist/types/analytics.d.ts.map +1 -0
- package/dist/types/analytics.js +2 -0
- package/dist/types/analytics.js.map +1 -0
- package/dist/types/business.d.ts +95 -0
- package/dist/types/business.d.ts.map +1 -0
- package/dist/types/business.js +2 -0
- package/dist/types/business.js.map +1 -0
- package/dist/types/buyer.d.ts +144 -0
- package/dist/types/buyer.d.ts.map +1 -0
- package/dist/types/buyer.js +45 -0
- package/dist/types/buyer.js.map +1 -0
- package/dist/types/campaign.d.ts +51 -0
- package/dist/types/campaign.d.ts.map +1 -0
- package/dist/types/campaign.js +2 -0
- package/dist/types/campaign.js.map +1 -0
- package/dist/types/cart.d.ts +40 -0
- package/dist/types/cart.d.ts.map +1 -0
- package/dist/types/cart.js +2 -0
- package/dist/types/cart.js.map +1 -0
- package/dist/types/catalog.d.ts +164 -0
- package/dist/types/catalog.d.ts.map +1 -0
- package/dist/types/catalog.js +2 -0
- package/dist/types/catalog.js.map +1 -0
- package/dist/types/cms.d.ts +196 -0
- package/dist/types/cms.d.ts.map +1 -0
- package/dist/types/cms.js +2 -0
- package/dist/types/cms.js.map +1 -0
- package/dist/types/cookie-consent.d.ts +18 -0
- package/dist/types/cookie-consent.d.ts.map +1 -0
- package/dist/types/cookie-consent.js +7 -0
- package/dist/types/cookie-consent.js.map +1 -0
- package/dist/types/guest-order.d.ts +16 -0
- package/dist/types/guest-order.d.ts.map +1 -0
- package/dist/types/guest-order.js +9 -0
- package/dist/types/guest-order.js.map +1 -0
- package/dist/types/listing.d.ts +14 -0
- package/dist/types/listing.d.ts.map +1 -0
- package/dist/types/listing.js +2 -0
- package/dist/types/listing.js.map +1 -0
- package/dist/types/order.d.ts +40 -0
- package/dist/types/order.d.ts.map +1 -0
- package/dist/types/order.js +2 -0
- package/dist/types/order.js.map +1 -0
- package/dist/types/seo.d.ts +93 -0
- package/dist/types/seo.d.ts.map +1 -0
- package/dist/types/seo.js +2 -0
- package/dist/types/seo.js.map +1 -0
- package/dist/types/server-env.d.ts +19 -0
- package/dist/types/server-env.d.ts.map +1 -0
- package/dist/types/server-env.js +10 -0
- package/dist/types/server-env.js.map +1 -0
- package/dist/types/wishlist.d.ts +10 -0
- package/dist/types/wishlist.d.ts.map +1 -0
- package/dist/types/wishlist.js +2 -0
- package/dist/types/wishlist.js.map +1 -0
- package/dist/wishlist/wishlist.d.ts +28 -0
- package/dist/wishlist/wishlist.d.ts.map +1 -0
- package/dist/wishlist/wishlist.js +42 -0
- package/dist/wishlist/wishlist.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -401,8 +401,11 @@ BUYER_AUTH_ERRORS.VERIFY_TOKEN_INVALID // "VERIFY_TOKEN_INVALID"
|
|
|
401
401
|
BUYER_AUTH_ERRORS.EMAIL_ALREADY_VERIFIED // "EMAIL_ALREADY_VERIFIED"
|
|
402
402
|
BUYER_AUTH_ERRORS.EMAIL_TAKEN // "Email already registered in this store"
|
|
403
403
|
BUYER_AUTH_ERRORS.MISSING_REQUIRED_FIELDS // "MISSING_REQUIRED_FIELDS"
|
|
404
|
+
BUYER_AUTH_ERRORS.CAPTCHA_REQUIRED // "CAPTCHA_REQUIRED" (Turnstile, HTTP 422)
|
|
404
405
|
```
|
|
405
406
|
|
|
407
|
+
**Helper:** `isCaptchaRequiredError(err)` — detecta `{ status: 422, data.detail: CAPTCHA_REQUIRED }` en login, registro y forgot-password.
|
|
408
|
+
|
|
406
409
|
---
|
|
407
410
|
|
|
408
411
|
## Carrito
|
|
@@ -586,29 +589,32 @@ BUYER_COOKIE_OPTIONS // { path: '/', httpOnly: true, sameSite: 'lax', maxAg
|
|
|
586
589
|
|
|
587
590
|
## Analytics
|
|
588
591
|
|
|
589
|
-
Cliente
|
|
592
|
+
Cliente singleton con batch, consent GDPR, sesión (`X-Session-ID`) y atribución first-touch (UTMs + click IDs).
|
|
593
|
+
|
|
594
|
+
**Documentación completa:** [`docs/13-analytics.md`](../../docs/13-analytics.md)
|
|
590
595
|
|
|
591
596
|
```ts
|
|
592
597
|
import { analytics } from '@proxima-io/storefront-core';
|
|
593
598
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
599
|
+
analytics.init(
|
|
600
|
+
{
|
|
601
|
+
apiUrl: 'https://api.proxima.io',
|
|
602
|
+
websiteId: 'uuid-website',
|
|
603
|
+
businessId: 'uuid-negocio',
|
|
604
|
+
locale: 'es',
|
|
605
|
+
sessionId: 'uuid-cart-session-from-ssr',
|
|
606
|
+
},
|
|
607
|
+
{ requireAnalyticsConsent: true },
|
|
608
|
+
);
|
|
603
609
|
|
|
604
|
-
|
|
605
|
-
analytics.track('product_view', { product_slug: 'titan-mx-pro' });
|
|
610
|
+
analytics.track('product_view', { product_slug: 'titan-mx-pro', price: 199.9 });
|
|
606
611
|
analytics.track('add_to_cart', { product_slug, variant_id: 42, price: 199.90 });
|
|
607
612
|
analytics.track('order_completed', { order_id: 'ord_123', order_total: 399.80 });
|
|
608
|
-
analytics.track('search', { query: 'zapatillas', results_count: 24 });
|
|
609
613
|
```
|
|
610
614
|
|
|
611
|
-
-
|
|
612
|
-
-
|
|
613
|
-
-
|
|
614
|
-
-
|
|
615
|
+
- Endpoint: **`POST /api/v1/storefront/events`** con headers `X-Business-ID` + `X-Session-ID`.
|
|
616
|
+
- `page_view` automático en init y `astro:page-load`.
|
|
617
|
+
- Flush periódico + `fetch(..., { keepalive: true })` al ocultar la pestaña.
|
|
618
|
+
- `captureSessionAttribution()` / `getSessionAttribution()` — ver doc § Marketing attribution.
|
|
619
|
+
- Helpers de consent: `acceptAllCookieConsent()`, `isAnalyticsConsentGranted()`, etc.
|
|
620
|
+
- Catálogo completo de eventos (`checkout_started`, `filter_applied`, `promotion_view`, …) en la doc.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ProximaApiConfig, ProximaWebsiteResponse } from '../types/cms.js';
|
|
2
|
+
import type { AddressInput, CustomerAddress, UbigeoResult } from '../types/address.js';
|
|
3
|
+
/** Fetch all saved addresses for the authenticated customer. */
|
|
4
|
+
export declare function fetchCustomerAddresses(config: Pick<ProximaApiConfig, "baseUrl">, website: Pick<ProximaWebsiteResponse, "business_id">, params: {
|
|
5
|
+
token: string;
|
|
6
|
+
}): Promise<CustomerAddress[]>;
|
|
7
|
+
/** Save a new address to the customer's address book. */
|
|
8
|
+
export declare function createCustomerAddress(config: Pick<ProximaApiConfig, "baseUrl">, website: Pick<ProximaWebsiteResponse, "business_id">, params: {
|
|
9
|
+
token: string;
|
|
10
|
+
address: AddressInput;
|
|
11
|
+
}): Promise<CustomerAddress>;
|
|
12
|
+
/** Partially update a saved address. Only the fields included in `address` are changed. */
|
|
13
|
+
export declare function updateCustomerAddress(config: Pick<ProximaApiConfig, "baseUrl">, website: Pick<ProximaWebsiteResponse, "business_id">, params: {
|
|
14
|
+
token: string;
|
|
15
|
+
addressId: number;
|
|
16
|
+
address: Partial<AddressInput>;
|
|
17
|
+
}): Promise<CustomerAddress>;
|
|
18
|
+
/** Delete a saved address. Throws if the address does not exist. */
|
|
19
|
+
export declare function deleteCustomerAddress(config: Pick<ProximaApiConfig, "baseUrl">, website: Pick<ProximaWebsiteResponse, "business_id">, params: {
|
|
20
|
+
token: string;
|
|
21
|
+
addressId: number;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
/** Mark an address as the customer's default. The previous default is unset automatically. */
|
|
24
|
+
export declare function setDefaultAddress(config: Pick<ProximaApiConfig, "baseUrl">, website: Pick<ProximaWebsiteResponse, "business_id">, params: {
|
|
25
|
+
token: string;
|
|
26
|
+
addressId: number;
|
|
27
|
+
}): Promise<CustomerAddress>;
|
|
28
|
+
/**
|
|
29
|
+
* Search Peruvian ubigeo codes (department/province/district) by name.
|
|
30
|
+
* Use this to power the address form's location selector.
|
|
31
|
+
* Returns an empty array on error instead of throwing.
|
|
32
|
+
*/
|
|
33
|
+
export declare function searchUbigeo(config: Pick<ProximaApiConfig, "baseUrl">, params: {
|
|
34
|
+
q: string;
|
|
35
|
+
}): Promise<UbigeoResult[]>;
|
|
36
|
+
//# sourceMappingURL=address-book.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address-book.d.ts","sourceRoot":"","sources":["../../src/addresses/address-book.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAMvF,gEAAgE;AAChE,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,EACzC,OAAO,EAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,EACpD,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACxB,OAAO,CAAC,eAAe,EAAE,CAAC,CAO5B;AAED,yDAAyD;AACzD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,EACzC,OAAO,EAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,EACpD,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC/C,OAAO,CAAC,eAAe,CAAC,CAW1B;AAED,2FAA2F;AAC3F,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,EACzC,OAAO,EAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,EACpD,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;CAAE,GAC3E,OAAO,CAAC,eAAe,CAAC,CAW1B;AAED,oEAAoE;AACpE,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,EACzC,OAAO,EAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,EACpD,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC3C,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,8FAA8F;AAC9F,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,EACzC,OAAO,EAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,EACpD,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC3C,OAAO,CAAC,eAAe,CAAC,CAW1B;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,EACzC,MAAM,EAAE;IAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GACpB,OAAO,CAAC,YAAY,EAAE,CAAC,CAMzB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { StorefrontEndpoints, createStorefrontClient } from '../api/index.js';
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Address Book
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
/** Fetch all saved addresses for the authenticated customer. */
|
|
6
|
+
export async function fetchCustomerAddresses(config, website, params) {
|
|
7
|
+
const client = createStorefrontClient(config);
|
|
8
|
+
return client.get(StorefrontEndpoints.buyer.addresses(), {
|
|
9
|
+
businessId: website.business_id,
|
|
10
|
+
token: params.token,
|
|
11
|
+
failPrefix: 'fetchCustomerAddresses failed',
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/** Save a new address to the customer's address book. */
|
|
15
|
+
export async function createCustomerAddress(config, website, params) {
|
|
16
|
+
const client = createStorefrontClient(config);
|
|
17
|
+
return client.post(StorefrontEndpoints.buyer.addresses(), params.address, {
|
|
18
|
+
businessId: website.business_id,
|
|
19
|
+
token: params.token,
|
|
20
|
+
failLabel: 'createCustomerAddress failed',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** Partially update a saved address. Only the fields included in `address` are changed. */
|
|
24
|
+
export async function updateCustomerAddress(config, website, params) {
|
|
25
|
+
const client = createStorefrontClient(config);
|
|
26
|
+
return client.patch(StorefrontEndpoints.buyer.address(params.addressId), params.address, {
|
|
27
|
+
businessId: website.business_id,
|
|
28
|
+
token: params.token,
|
|
29
|
+
failLabel: 'updateCustomerAddress failed',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/** Delete a saved address. Throws if the address does not exist. */
|
|
33
|
+
export async function deleteCustomerAddress(config, website, params) {
|
|
34
|
+
const client = createStorefrontClient(config);
|
|
35
|
+
await client.delete(StorefrontEndpoints.buyer.address(params.addressId), {
|
|
36
|
+
businessId: website.business_id,
|
|
37
|
+
token: params.token,
|
|
38
|
+
failPrefix: 'deleteCustomerAddress failed',
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** Mark an address as the customer's default. The previous default is unset automatically. */
|
|
42
|
+
export async function setDefaultAddress(config, website, params) {
|
|
43
|
+
const client = createStorefrontClient(config);
|
|
44
|
+
return client.post(StorefrontEndpoints.buyer.defaultAddress(params.addressId), undefined, {
|
|
45
|
+
businessId: website.business_id,
|
|
46
|
+
token: params.token,
|
|
47
|
+
failPrefix: 'setDefaultAddress failed',
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Search Peruvian ubigeo codes (department/province/district) by name.
|
|
52
|
+
* Use this to power the address form's location selector.
|
|
53
|
+
* Returns an empty array on error instead of throwing.
|
|
54
|
+
*/
|
|
55
|
+
export async function searchUbigeo(config, params) {
|
|
56
|
+
const client = createStorefrontClient(config);
|
|
57
|
+
return client.get(StorefrontEndpoints.catalog.ubigeos(), {
|
|
58
|
+
query: { q: params.q },
|
|
59
|
+
fallback: [],
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=address-book.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address-book.js","sourceRoot":"","sources":["../../src/addresses/address-book.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { StorefrontAnalyticsConfig, StorefrontEventPayload, StorefrontEventType } from '../types/analytics.js';
|
|
2
|
+
export interface StorefrontAnalyticsInitOptions {
|
|
3
|
+
/**
|
|
4
|
+
* When true, `init()` buffers until the shopper grants analytics consent
|
|
5
|
+
* (`acceptAllCookieConsent()`). Pair with a cookie banner UI.
|
|
6
|
+
*/
|
|
7
|
+
requireAnalyticsConsent?: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare class ProximaAnalytics {
|
|
10
|
+
private config;
|
|
11
|
+
private pendingConfig;
|
|
12
|
+
private queue;
|
|
13
|
+
private preInitQueue;
|
|
14
|
+
private timer;
|
|
15
|
+
private initialized;
|
|
16
|
+
private consentRequired;
|
|
17
|
+
init(config: StorefrontAnalyticsConfig, options?: StorefrontAnalyticsInitOptions): void;
|
|
18
|
+
/** Resume init after the shopper grants analytics consent. */
|
|
19
|
+
resumeFromConsent(): void;
|
|
20
|
+
private start;
|
|
21
|
+
track(type: StorefrontEventType, payload?: StorefrontEventPayload): void;
|
|
22
|
+
flush(beacon?: boolean): void;
|
|
23
|
+
destroy(): void;
|
|
24
|
+
}
|
|
25
|
+
/** Singleton analytics client. Call `analytics.init()` once from SiteLayout. */
|
|
26
|
+
export declare const analytics: ProximaAnalytics;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=analytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/analytics/analytics.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEpH,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAYD,cAAM,gBAAgB;IACpB,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,YAAY,CAA4D;IAChF,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAS;IAEhC,IAAI,CAAC,MAAM,EAAE,yBAAyB,EAAE,OAAO,CAAC,EAAE,8BAA8B,GAAG,IAAI;IAUvF,8DAA8D;IAC9D,iBAAiB,IAAI,IAAI;IASzB,OAAO,CAAC,KAAK;IAyBb,KAAK,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,GAAE,sBAA2B,GAAG,IAAI;IAwB5E,KAAK,CAAC,MAAM,UAAQ,GAAG,IAAI;IAqB3B,OAAO,IAAI,IAAI;CAUhB;AAED,gFAAgF;AAChF,eAAO,MAAM,SAAS,kBAAyB,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { StorefrontEndpoints } from '../api/endpoints.js';
|
|
2
|
+
import { isAnalyticsConsentGranted, onCookieConsentChanged } from '../cookie-consent/consent.js';
|
|
3
|
+
import { getSessionAttribution, captureSessionAttribution } from './attribution.js';
|
|
4
|
+
import { resolveAnalyticsSessionId } from './session.js';
|
|
5
|
+
class ProximaAnalytics {
|
|
6
|
+
config = null;
|
|
7
|
+
pendingConfig = null;
|
|
8
|
+
queue = [];
|
|
9
|
+
preInitQueue = [];
|
|
10
|
+
timer = null;
|
|
11
|
+
initialized = false;
|
|
12
|
+
consentRequired = false;
|
|
13
|
+
init(config, options) {
|
|
14
|
+
if (typeof window === 'undefined')
|
|
15
|
+
return;
|
|
16
|
+
if (options?.requireAnalyticsConsent) {
|
|
17
|
+
this.consentRequired = true;
|
|
18
|
+
this.pendingConfig = config;
|
|
19
|
+
if (!isAnalyticsConsentGranted())
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
this.start(config);
|
|
23
|
+
}
|
|
24
|
+
/** Resume init after the shopper grants analytics consent. */
|
|
25
|
+
resumeFromConsent() {
|
|
26
|
+
if (typeof window === 'undefined')
|
|
27
|
+
return;
|
|
28
|
+
if (this.initialized)
|
|
29
|
+
return;
|
|
30
|
+
if (!this.consentRequired || !isAnalyticsConsentGranted())
|
|
31
|
+
return;
|
|
32
|
+
const config = this.pendingConfig ?? this.config;
|
|
33
|
+
if (!config)
|
|
34
|
+
return;
|
|
35
|
+
this.start(config);
|
|
36
|
+
}
|
|
37
|
+
start(config) {
|
|
38
|
+
if (typeof window === 'undefined')
|
|
39
|
+
return;
|
|
40
|
+
this.config = config;
|
|
41
|
+
this.pendingConfig = null;
|
|
42
|
+
if (this.initialized)
|
|
43
|
+
return;
|
|
44
|
+
this.initialized = true;
|
|
45
|
+
captureSessionAttribution();
|
|
46
|
+
for (const [type, payload] of this.preInitQueue.splice(0)) {
|
|
47
|
+
this.track(type, payload);
|
|
48
|
+
}
|
|
49
|
+
const firePageView = () => this.track('page_view');
|
|
50
|
+
firePageView();
|
|
51
|
+
document.addEventListener('astro:page-load', firePageView);
|
|
52
|
+
const interval = config.flushInterval ?? 3000;
|
|
53
|
+
this.timer = setInterval(() => this.flush(), interval);
|
|
54
|
+
document.addEventListener('visibilitychange', () => {
|
|
55
|
+
if (document.visibilityState === 'hidden')
|
|
56
|
+
this.flush(true);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
track(type, payload = {}) {
|
|
60
|
+
if (typeof window === 'undefined')
|
|
61
|
+
return;
|
|
62
|
+
if (!this.config) {
|
|
63
|
+
this.preInitQueue.push([type, payload]);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const attribution = getSessionAttribution();
|
|
67
|
+
const hasAttribution = Object.keys(attribution).length > 0;
|
|
68
|
+
const mergedPayload = hasAttribution
|
|
69
|
+
? { ...payload, attribution }
|
|
70
|
+
: payload;
|
|
71
|
+
const event = {
|
|
72
|
+
event_type: type,
|
|
73
|
+
occurred_at: new Date().toISOString(),
|
|
74
|
+
website_id: this.config.websiteId,
|
|
75
|
+
path: window.location.pathname,
|
|
76
|
+
referrer: document.referrer || undefined,
|
|
77
|
+
locale: this.config.locale,
|
|
78
|
+
payload: mergedPayload,
|
|
79
|
+
};
|
|
80
|
+
this.queue.push(event);
|
|
81
|
+
if (this.config.debug)
|
|
82
|
+
console.debug('[proxima:analytics] queued', event);
|
|
83
|
+
}
|
|
84
|
+
flush(beacon = false) {
|
|
85
|
+
if (!this.config || this.queue.length === 0)
|
|
86
|
+
return;
|
|
87
|
+
const batch = this.queue.splice(0);
|
|
88
|
+
const url = `${this.config.apiUrl.replace(/\/$/, '')}${StorefrontEndpoints.analytics.events()}`;
|
|
89
|
+
const body = JSON.stringify({ events: batch });
|
|
90
|
+
const sessionId = resolveAnalyticsSessionId(this.config);
|
|
91
|
+
const headers = {
|
|
92
|
+
'Content-Type': 'application/json',
|
|
93
|
+
'X-Business-ID': this.config.businessId,
|
|
94
|
+
'X-Session-ID': sessionId,
|
|
95
|
+
};
|
|
96
|
+
if (this.config.debug) {
|
|
97
|
+
console.debug(`[proxima:analytics] flushing ${batch.length} event(s) → ${url}`);
|
|
98
|
+
}
|
|
99
|
+
void fetch(url, { method: 'POST', headers, body, keepalive: true }).catch(() => {
|
|
100
|
+
if (beacon)
|
|
101
|
+
this.queue.unshift(...batch);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
destroy() {
|
|
105
|
+
if (this.timer !== null)
|
|
106
|
+
clearInterval(this.timer);
|
|
107
|
+
this.timer = null;
|
|
108
|
+
this.initialized = false;
|
|
109
|
+
this.consentRequired = false;
|
|
110
|
+
this.pendingConfig = null;
|
|
111
|
+
this.config = null;
|
|
112
|
+
this.queue = [];
|
|
113
|
+
this.preInitQueue = [];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** Singleton analytics client. Call `analytics.init()` once from SiteLayout. */
|
|
117
|
+
export const analytics = new ProximaAnalytics();
|
|
118
|
+
if (typeof window !== 'undefined') {
|
|
119
|
+
onCookieConsentChanged((state) => {
|
|
120
|
+
if (state.analytics)
|
|
121
|
+
analytics.resumeFromConsent();
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=analytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/analytics/analytics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Session-scoped first-touch marketing attribution (UTMs + ad click IDs). */
|
|
2
|
+
export declare const ATTRIBUTION_STORAGE_KEY = "pxa_session_attribution";
|
|
3
|
+
export interface SessionAttribution {
|
|
4
|
+
utm_source?: string;
|
|
5
|
+
utm_medium?: string;
|
|
6
|
+
utm_campaign?: string;
|
|
7
|
+
utm_content?: string;
|
|
8
|
+
utm_term?: string;
|
|
9
|
+
gclid?: string;
|
|
10
|
+
fbclid?: string;
|
|
11
|
+
msclkid?: string;
|
|
12
|
+
/** Path + query of the landing hit in this tab session. */
|
|
13
|
+
landing_path?: string;
|
|
14
|
+
/** document.referrer on the landing hit. */
|
|
15
|
+
landing_referrer?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Best-effort channel guess when paid UTMs are absent (organic/social/direct). */
|
|
18
|
+
export declare function inferAttributionFromReferrer(referrer: string): Partial<SessionAttribution>;
|
|
19
|
+
/**
|
|
20
|
+
* Capture first-touch attribution for the current browser tab session.
|
|
21
|
+
* UTMs / click IDs from the landing URL win; subsequent navigations keep the snapshot.
|
|
22
|
+
*/
|
|
23
|
+
export declare function captureSessionAttribution(): SessionAttribution;
|
|
24
|
+
/** Returns the stored session attribution (capturing on first call). */
|
|
25
|
+
export declare function getSessionAttribution(): SessionAttribution;
|
|
26
|
+
/** Test helper — clears stored attribution. */
|
|
27
|
+
export declare function clearSessionAttribution(): void;
|
|
28
|
+
//# sourceMappingURL=attribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribution.d.ts","sourceRoot":"","sources":["../../src/analytics/attribution.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AAEjE,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AA+CD,mFAAmF;AACnF,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkB1F;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,kBAAkB,CAuB9D;AAED,wEAAwE;AACxE,wBAAgB,qBAAqB,IAAI,kBAAkB,CAE1D;AAED,+CAA+C;AAC/C,wBAAgB,uBAAuB,IAAI,IAAI,CAO9C"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/** Session-scoped first-touch marketing attribution (UTMs + ad click IDs). */
|
|
2
|
+
export const ATTRIBUTION_STORAGE_KEY = 'pxa_session_attribution';
|
|
3
|
+
const UTM_KEYS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
|
|
4
|
+
const CLICK_ID_KEYS = ['gclid', 'fbclid', 'msclkid'];
|
|
5
|
+
const MAX_VALUE_LEN = 256;
|
|
6
|
+
function trimValue(raw) {
|
|
7
|
+
const value = raw?.trim();
|
|
8
|
+
if (!value)
|
|
9
|
+
return undefined;
|
|
10
|
+
return value.length > MAX_VALUE_LEN ? value.slice(0, MAX_VALUE_LEN) : value;
|
|
11
|
+
}
|
|
12
|
+
function readStored() {
|
|
13
|
+
if (typeof window === 'undefined')
|
|
14
|
+
return null;
|
|
15
|
+
try {
|
|
16
|
+
const raw = window.localStorage?.getItem(ATTRIBUTION_STORAGE_KEY);
|
|
17
|
+
if (!raw)
|
|
18
|
+
return null;
|
|
19
|
+
const parsed = JSON.parse(raw);
|
|
20
|
+
return parsed && typeof parsed === 'object' ? parsed : null;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function writeStored(value) {
|
|
27
|
+
if (typeof window === 'undefined' || !window.localStorage)
|
|
28
|
+
return;
|
|
29
|
+
try {
|
|
30
|
+
window.localStorage.setItem(ATTRIBUTION_STORAGE_KEY, JSON.stringify(value));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* private mode */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function readFromSearchParams(search) {
|
|
37
|
+
const out = {};
|
|
38
|
+
for (const key of UTM_KEYS) {
|
|
39
|
+
const value = trimValue(search.get(key));
|
|
40
|
+
if (value)
|
|
41
|
+
out[key] = value;
|
|
42
|
+
}
|
|
43
|
+
for (const key of CLICK_ID_KEYS) {
|
|
44
|
+
const value = trimValue(search.get(key));
|
|
45
|
+
if (value)
|
|
46
|
+
out[key] = value;
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/** Best-effort channel guess when paid UTMs are absent (organic/social/direct). */
|
|
51
|
+
export function inferAttributionFromReferrer(referrer) {
|
|
52
|
+
if (!referrer.trim())
|
|
53
|
+
return {};
|
|
54
|
+
try {
|
|
55
|
+
const host = new URL(referrer).hostname.replace(/^www\./i, '').toLowerCase();
|
|
56
|
+
if (host === 't.co' || host.endsWith('.twitter.com') || host === 'twitter.com' || host === 'x.com') {
|
|
57
|
+
return { utm_source: 'twitter', utm_medium: 'social' };
|
|
58
|
+
}
|
|
59
|
+
if (host.includes('google.'))
|
|
60
|
+
return { utm_source: 'google', utm_medium: 'organic' };
|
|
61
|
+
if (host.includes('facebook.com') || host.includes('instagram.com') || host.includes('l.facebook.com')) {
|
|
62
|
+
return { utm_source: 'facebook', utm_medium: 'social' };
|
|
63
|
+
}
|
|
64
|
+
if (host.includes('bing.com'))
|
|
65
|
+
return { utm_source: 'bing', utm_medium: 'organic' };
|
|
66
|
+
if (host.includes('tiktok.com'))
|
|
67
|
+
return { utm_source: 'tiktok', utm_medium: 'social' };
|
|
68
|
+
if (host.includes('youtube.com'))
|
|
69
|
+
return { utm_source: 'youtube', utm_medium: 'social' };
|
|
70
|
+
return { utm_source: host, utm_medium: 'referral' };
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return {};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Capture first-touch attribution for the current browser tab session.
|
|
78
|
+
* UTMs / click IDs from the landing URL win; subsequent navigations keep the snapshot.
|
|
79
|
+
*/
|
|
80
|
+
export function captureSessionAttribution() {
|
|
81
|
+
if (typeof window === 'undefined')
|
|
82
|
+
return {};
|
|
83
|
+
const stored = readStored();
|
|
84
|
+
if (stored)
|
|
85
|
+
return stored;
|
|
86
|
+
const href = window.location.href;
|
|
87
|
+
const url = new URL(href);
|
|
88
|
+
const fromUrl = readFromSearchParams(url.searchParams);
|
|
89
|
+
const landingReferrer = document.referrer?.trim() || undefined;
|
|
90
|
+
const attribution = {
|
|
91
|
+
landing_path: `${url.pathname}${url.search}`,
|
|
92
|
+
landing_referrer: landingReferrer,
|
|
93
|
+
...fromUrl,
|
|
94
|
+
};
|
|
95
|
+
if (!attribution.utm_source && landingReferrer) {
|
|
96
|
+
Object.assign(attribution, inferAttributionFromReferrer(landingReferrer));
|
|
97
|
+
}
|
|
98
|
+
writeStored(attribution);
|
|
99
|
+
return attribution;
|
|
100
|
+
}
|
|
101
|
+
/** Returns the stored session attribution (capturing on first call). */
|
|
102
|
+
export function getSessionAttribution() {
|
|
103
|
+
return captureSessionAttribution();
|
|
104
|
+
}
|
|
105
|
+
/** Test helper — clears stored attribution. */
|
|
106
|
+
export function clearSessionAttribution() {
|
|
107
|
+
if (typeof window === 'undefined')
|
|
108
|
+
return;
|
|
109
|
+
try {
|
|
110
|
+
window.localStorage.removeItem(ATTRIBUTION_STORAGE_KEY);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
/* ignore */
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=attribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribution.js","sourceRoot":"","sources":["../../src/analytics/attribution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { StorefrontAnalyticsConfig } from '../types/analytics.js';
|
|
2
|
+
export declare const ANALYTICS_SESSION_STORAGE_KEY = "pxa_analytics_session";
|
|
3
|
+
export interface ResolveAnalyticsSessionIdOptions {
|
|
4
|
+
cookieName?: string;
|
|
5
|
+
storageKey?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the browser session id sent as `X-Session-ID` on analytics batches.
|
|
9
|
+
* Priority: config.sessionId → config.getSessionId() → readable cart cookie → localStorage UUID.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveAnalyticsSessionId(config?: Pick<StorefrontAnalyticsConfig, 'sessionId' | 'getSessionId' | 'cartSessionCookieName'>, options?: ResolveAnalyticsSessionIdOptions): string;
|
|
12
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/analytics/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAEvE,eAAO,MAAM,6BAA6B,0BAA0B,CAAC;AAsCrE,MAAM,WAAW,gCAAgC;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,CAAC,EAAE,IAAI,CAAC,yBAAyB,EAAE,WAAW,GAAG,cAAc,GAAG,uBAAuB,CAAC,EAChG,OAAO,CAAC,EAAE,gCAAgC,GACzC,MAAM,CAuBR"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const ANALYTICS_SESSION_STORAGE_KEY = 'pxa_analytics_session';
|
|
2
|
+
const DEFAULT_CART_SESSION_COOKIE = 'cart_session_id';
|
|
3
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
4
|
+
function isBrowser() {
|
|
5
|
+
return typeof window !== 'undefined';
|
|
6
|
+
}
|
|
7
|
+
function readCookie(name) {
|
|
8
|
+
if (!isBrowser())
|
|
9
|
+
return null;
|
|
10
|
+
const prefix = `${name}=`;
|
|
11
|
+
for (const part of document.cookie.split(';')) {
|
|
12
|
+
const trimmed = part.trim();
|
|
13
|
+
if (trimmed.startsWith(prefix)) {
|
|
14
|
+
return decodeURIComponent(trimmed.slice(prefix.length));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
function isUuid(value) {
|
|
20
|
+
return UUID_RE.test(value);
|
|
21
|
+
}
|
|
22
|
+
function createSessionId() {
|
|
23
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
24
|
+
return crypto.randomUUID();
|
|
25
|
+
}
|
|
26
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
27
|
+
const r = (Math.random() * 16) | 0;
|
|
28
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
29
|
+
return v.toString(16);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the browser session id sent as `X-Session-ID` on analytics batches.
|
|
34
|
+
* Priority: config.sessionId → config.getSessionId() → readable cart cookie → localStorage UUID.
|
|
35
|
+
*/
|
|
36
|
+
export function resolveAnalyticsSessionId(config, options) {
|
|
37
|
+
const explicit = config?.sessionId?.trim();
|
|
38
|
+
if (explicit && isUuid(explicit))
|
|
39
|
+
return explicit;
|
|
40
|
+
const fromGetter = config?.getSessionId?.()?.trim();
|
|
41
|
+
if (fromGetter && isUuid(fromGetter))
|
|
42
|
+
return fromGetter;
|
|
43
|
+
const cookieName = config?.cartSessionCookieName ?? options?.cookieName ?? DEFAULT_CART_SESSION_COOKIE;
|
|
44
|
+
const fromCookie = readCookie(cookieName)?.trim();
|
|
45
|
+
if (fromCookie && isUuid(fromCookie))
|
|
46
|
+
return fromCookie;
|
|
47
|
+
if (!isBrowser())
|
|
48
|
+
return createSessionId();
|
|
49
|
+
const storageKey = options?.storageKey ?? ANALYTICS_SESSION_STORAGE_KEY;
|
|
50
|
+
try {
|
|
51
|
+
const stored = localStorage.getItem(storageKey)?.trim();
|
|
52
|
+
if (stored && isUuid(stored))
|
|
53
|
+
return stored;
|
|
54
|
+
const created = createSessionId();
|
|
55
|
+
localStorage.setItem(storageKey, created);
|
|
56
|
+
return created;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return createSessionId();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/analytics/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { analytics } from './analytics.js';
|
|
2
|
+
import type { StorefrontAnalyticsConfig, StorefrontEventPayload } from '../types/analytics.js';
|
|
3
|
+
type AnalyticsClient = Pick<typeof analytics, 'init' | 'track' | 'flush'>;
|
|
4
|
+
/** Thin typed wrappers — optional DX layer over the analytics singleton. */
|
|
5
|
+
export declare function createStorefrontAnalyticsTrackers(client?: AnalyticsClient): {
|
|
6
|
+
init: (config: StorefrontAnalyticsConfig, options?: Parameters<typeof analytics.init>[1]) => void;
|
|
7
|
+
flush: (beacon?: boolean) => void;
|
|
8
|
+
pageView: () => void;
|
|
9
|
+
productView: (payload: StorefrontEventPayload) => void;
|
|
10
|
+
categoryView: (payload: StorefrontEventPayload) => void;
|
|
11
|
+
brandView: (payload: StorefrontEventPayload) => void;
|
|
12
|
+
search: (query: string, resultsCount: number) => void;
|
|
13
|
+
addToCart: (payload: StorefrontEventPayload) => void;
|
|
14
|
+
removeFromCart: (payload: StorefrontEventPayload) => void;
|
|
15
|
+
cartView: (payload: StorefrontEventPayload) => void;
|
|
16
|
+
checkoutStarted: (payload: StorefrontEventPayload) => void;
|
|
17
|
+
checkoutError: (payload: StorefrontEventPayload) => void;
|
|
18
|
+
orderCompleted: (payload: StorefrontEventPayload) => void;
|
|
19
|
+
notFound: (payload: StorefrontEventPayload) => void;
|
|
20
|
+
filterApplied: (payload: StorefrontEventPayload) => void;
|
|
21
|
+
sortChanged: (payload: StorefrontEventPayload) => void;
|
|
22
|
+
promotionView: (payload: StorefrontEventPayload) => void;
|
|
23
|
+
wishlistAdd: (payload: StorefrontEventPayload) => void;
|
|
24
|
+
loginCompleted: (method?: string) => void;
|
|
25
|
+
registerCompleted: () => void;
|
|
26
|
+
};
|
|
27
|
+
export type StorefrontAnalyticsTrackers = ReturnType<typeof createStorefrontAnalyticsTrackers>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=trackers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trackers.d.ts","sourceRoot":"","sources":["../../src/analytics/trackers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,sBAAsB,EAAuB,MAAM,uBAAuB,CAAC;AAEpH,KAAK,eAAe,GAAG,IAAI,CAAC,OAAO,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC;AAM1E,4EAA4E;AAC5E,wBAAgB,iCAAiC,CAAC,MAAM,GAAE,eAA2B;mBAElE,yBAAyB,YAAY,UAAU,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;qBAEvE,OAAO;;2BAED,sBAAsB;4BACrB,sBAAsB;yBACzB,sBAAsB;oBAC3B,MAAM,gBAAgB,MAAM;yBAEvB,sBAAsB;8BACjB,sBAAsB;wBAC5B,sBAAsB;+BACf,sBAAsB;6BACxB,sBAAsB;8BACrB,sBAAsB;wBAC5B,sBAAsB;6BACjB,sBAAsB;2BACxB,sBAAsB;6BACpB,sBAAsB;2BACxB,sBAAsB;;;EAIhD;AAED,MAAM,MAAM,2BAA2B,GAAG,UAAU,CAAC,OAAO,iCAAiC,CAAC,CAAC"}
|