@cartbase/storefront 0.14.0 → 0.15.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 +9 -3
- package/package.json +2 -1
- package/src/api/customers.ts +4 -7
- package/src/api/products.ts +4 -0
- package/src/cart-drawer/context.tsx +11 -1
- package/src/cart-drawer/item/variant.tsx +8 -3
- package/src/checkout/checkout-client.tsx +10 -1
- package/src/checkout/line-item-card.tsx +5 -2
- package/src/checkout/order-summary.tsx +9 -5
- package/src/common/country-select.tsx +11 -65
- package/src/common/index.ts +2 -0
- package/src/common/market-select.tsx +57 -0
- package/src/lib/variant-caption.ts +32 -0
- package/src/locales/context.ts +37 -0
- package/src/locales/provider.tsx +17 -21
- package/src/locales/types.ts +24 -21
- package/src/order/order-completed-template.tsx +10 -4
- package/src/order/order-item.tsx +4 -4
- package/src/products/product-template.tsx +11 -9
- package/src/products/related-products.tsx +9 -9
- package/src/reviews-ui/photo-upload.tsx +2 -1
- package/src/reviews-ui/review-list.tsx +4 -2
- package/src/reviews-ui/review-widget.tsx +4 -1
- package/src/reviews-ui/review-wizard.tsx +3 -2
- package/src/store/category-template.tsx +8 -1
- package/src/store/collection-template.tsx +8 -1
- package/src/store/search-template.tsx +10 -4
- package/src/store/store-template.tsx +10 -4
- package/src/tracking/chatgpt-pixel.tsx +17 -10
- package/src/tracking/consent-init.tsx +62 -44
- package/src/tracking/consent.ts +58 -7
- package/src/tracking/index.ts +2 -0
- package/src/tracking/meta-pixel.tsx +27 -15
- package/src/tracking/storefront-tags.tsx +14 -7
- package/src/tracking/tiktok-pixel.tsx +15 -7
- package/src/tracking/types.ts +5 -2
|
@@ -22,10 +22,15 @@ import type { TrackingConfig } from "./types"
|
|
|
22
22
|
* it at the next deploy.
|
|
23
23
|
*
|
|
24
24
|
* Consent: nothing extra to wire. <ConsentInit> sets the Consent Mode v2
|
|
25
|
-
* defaults synchronously ahead of these, the Meta
|
|
26
|
-
* the
|
|
27
|
-
* `applyConsent()` relays a live decision to
|
|
28
|
-
* AFTER <ConsentInit> and the gate holds.
|
|
25
|
+
* defaults synchronously ahead of these, the Meta, TikTok and ChatGPT
|
|
26
|
+
* snippets resolve the same decision before they are allowed to send, and
|
|
27
|
+
* `applyConsent()` relays a live decision to every vendor. Mount this
|
|
28
|
+
* AFTER <ConsentInit> and the gate holds. Whether there IS a gate is the
|
|
29
|
+
* store's own setting, `consent_required` on this same block: a store that
|
|
30
|
+
* collects consent starts every visitor denied until they choose, a store
|
|
31
|
+
* with the banner off starts them granted, and a stored choice wins either
|
|
32
|
+
* way. The block always carries the flag; an absent one is read as
|
|
33
|
+
* required, the closed side.
|
|
29
34
|
*
|
|
30
35
|
* Google is deliberately ONE tag with two destinations rather than two
|
|
31
36
|
* loaders — see the comment block in ./ga4.tsx. It is also why the Ads
|
|
@@ -56,6 +61,8 @@ export async function StorefrontTags({
|
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
const consentRequired = tracking.consent_required ?? true
|
|
65
|
+
|
|
59
66
|
return (
|
|
60
67
|
<>
|
|
61
68
|
{/* Cartbase's own analytics, always on and never a merchant setting:
|
|
@@ -64,9 +71,9 @@ export async function StorefrontTags({
|
|
|
64
71
|
only appear when the merchant has entered their ids. */}
|
|
65
72
|
<PageViews />
|
|
66
73
|
<LiveHeartbeat />
|
|
67
|
-
<MetaPixel pixelId={tracking.facebookPixel?.pixelId} />
|
|
68
|
-
<TikTokPixel pixelId={tracking.tiktok?.pixelId} />
|
|
69
|
-
<ChatGptPixel pixelId={tracking.chatgptAds?.pixelId} />
|
|
74
|
+
<MetaPixel pixelId={tracking.facebookPixel?.pixelId} consentRequired={consentRequired} />
|
|
75
|
+
<TikTokPixel pixelId={tracking.tiktok?.pixelId} consentRequired={consentRequired} />
|
|
76
|
+
<ChatGptPixel pixelId={tracking.chatgptAds?.pixelId} consentRequired={consentRequired} />
|
|
70
77
|
<GoogleTag
|
|
71
78
|
measurementId={tracking.ga4?.measurementId}
|
|
72
79
|
adsConversionId={tracking.googleAds?.conversionId}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import Script from "next/script"
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { adsConsentSnippet } from "./consent"
|
|
6
6
|
import { jsStringLiteral } from "./inline-script"
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -33,6 +33,11 @@ import { jsStringLiteral } from "./inline-script"
|
|
|
33
33
|
*
|
|
34
34
|
* Live decisions arrive through `applyConsent()` in ./consent.ts, which
|
|
35
35
|
* relays to gtag, fbq and ttq together — there is no cookie watcher.
|
|
36
|
+
* The first decision is the store's default overridden by the visitor's
|
|
37
|
+
* stored choice (`adsConsentSnippet`): revoked on a store that collects
|
|
38
|
+
* consent, granted on a store with no consent gate, the cookie winning
|
|
39
|
+
* either way. `consentRequired` is `tracking.consent_required`, passed by
|
|
40
|
+
* <StorefrontTags>, and required for the reason <ConsentInit> gives.
|
|
36
41
|
*
|
|
37
42
|
* One dependency outside the code: Cookie Consent Mode must be switched
|
|
38
43
|
* on for this pixel in TikTok Events Manager. With it off, `holdConsent`
|
|
@@ -43,7 +48,14 @@ import { jsStringLiteral } from "./inline-script"
|
|
|
43
48
|
* Renders nothing when `pixelId` is falsy, so a layout can mount it
|
|
44
49
|
* unconditionally.
|
|
45
50
|
*/
|
|
46
|
-
export function TikTokPixel({
|
|
51
|
+
export function TikTokPixel({
|
|
52
|
+
pixelId,
|
|
53
|
+
consentRequired,
|
|
54
|
+
}: {
|
|
55
|
+
pixelId?: string
|
|
56
|
+
/** `tracking.consent_required`: does this store collect consent before it tracks? */
|
|
57
|
+
consentRequired: boolean
|
|
58
|
+
}) {
|
|
47
59
|
if (!pixelId) return null
|
|
48
60
|
|
|
49
61
|
const id = jsStringLiteral(pixelId)
|
|
@@ -63,11 +75,7 @@ export function TikTokPixel({ pixelId }: { pixelId?: string }) {
|
|
|
63
75
|
ttq.page();
|
|
64
76
|
|
|
65
77
|
(function(){
|
|
66
|
-
|
|
67
|
-
try{
|
|
68
|
-
var m=d.cookie.match(/(?:^|; )${CONSENT_COOKIE}=([^;]*)/);
|
|
69
|
-
if(m){ads=!!JSON.parse(decodeURIComponent(m[1])).ads;}
|
|
70
|
-
}catch(e){}
|
|
78
|
+
${adsConsentSnippet(consentRequired, "d")}
|
|
71
79
|
if(ads){ttq.grantConsent();}else{ttq.revokeConsent();}
|
|
72
80
|
})();
|
|
73
81
|
}(window, document, 'ttq');
|
package/src/tracking/types.ts
CHANGED
|
@@ -48,8 +48,11 @@ export type TrackingConfig = {
|
|
|
48
48
|
* token and stays on the platform, read by the order.placed forwarder
|
|
49
49
|
* (chatgpt-ads-pixel card). */
|
|
50
50
|
chatgptAds?: { pixelId: string }
|
|
51
|
-
/**
|
|
52
|
-
*
|
|
51
|
+
/** Whether this store collects consent before it tracks (the consent
|
|
52
|
+
* CMP's `enabled`). True: every tag starts denied until the visitor
|
|
53
|
+
* chooses on the banner. False: the store has no consent gate and every
|
|
54
|
+
* tag starts granted. A choice stored in `_1c_consent` wins either way.
|
|
55
|
+
* Always served; a reader treats an absent value as true. */
|
|
53
56
|
consent_required?: boolean
|
|
54
57
|
}
|
|
55
58
|
|