@buildbase/sdk 0.0.71 → 0.0.74

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +43 -10
  3. package/dist/cli.mjs +2 -0
  4. package/dist/css/styles.css +1 -1
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.d.ts +103 -2
  7. package/dist/index.mjs +1 -1
  8. package/dist/mcp/index.cjs +1 -1
  9. package/dist/mcp/index.d.ts +30 -0
  10. package/dist/mcp/index.mjs +1 -1
  11. package/dist/react/chunks/SettingsDialog-C0ocJMBA.cjs +2 -0
  12. package/dist/react/chunks/SettingsDialog-CWrmSyKV.mjs +2 -0
  13. package/dist/react/chunks/{SubscriptionDialog-Bkue_qyM.cjs → SubscriptionDialog-CLh4zW9Y.cjs} +1 -1
  14. package/dist/react/chunks/{SubscriptionDialog-ZjdyTmxn.mjs → SubscriptionDialog-sH0cQdPD.mjs} +1 -1
  15. package/dist/react/chunks/react-BBSVsY3n.cjs +2 -0
  16. package/dist/react/chunks/react-CNHfoa5L.mjs +2 -0
  17. package/dist/react/index.cjs +1 -1
  18. package/dist/react/index.d.ts +130 -8
  19. package/dist/react/index.mjs +1 -1
  20. package/dist/server/browser.cjs +1 -0
  21. package/dist/server/browser.mjs +1 -0
  22. package/dist/server/index.cjs +1 -0
  23. package/dist/server/index.d.ts +556 -0
  24. package/dist/server/index.mjs +1 -0
  25. package/dist/server/next/index.cjs +1 -0
  26. package/dist/server/next/index.d.ts +156 -0
  27. package/dist/server/next/index.mjs +1 -0
  28. package/dist/tracking/index.cjs +1 -1
  29. package/dist/tracking/index.d.ts +205 -8
  30. package/dist/tracking/index.mjs +1 -1
  31. package/docs/SERVER-CONTENT.md +297 -0
  32. package/package.json +65 -5
  33. package/dist/react/chunks/SettingsDialog-D5lLHG9-.cjs +0 -2
  34. package/dist/react/chunks/SettingsDialog-DiTnAWFt.mjs +0 -2
  35. package/dist/react/chunks/react-BIZcTNos.mjs +0 -2
  36. package/dist/react/chunks/react-DM1nGVlR.cjs +0 -2
  37. /package/dist/react/chunks/{ar-D_agqxXa.cjs → ar-CRVhjpVE.cjs} +0 -0
  38. /package/dist/react/chunks/{ar-By_nJtJ6.mjs → ar-DFPDdu2U.mjs} +0 -0
  39. /package/dist/react/chunks/{de-D7j-9T8u.cjs → de-BGhzn711.cjs} +0 -0
  40. /package/dist/react/chunks/{de-CQW2yLLr.mjs → de-Bqi8scew.mjs} +0 -0
  41. /package/dist/react/chunks/{es-CggBj8dc.mjs → es-D_Eqhob3.mjs} +0 -0
  42. /package/dist/react/chunks/{es-DYtfnqFg.cjs → es-DyrMaeUp.cjs} +0 -0
  43. /package/dist/react/chunks/{fr-Bu6_05LA.cjs → fr-C0SkloRr.cjs} +0 -0
  44. /package/dist/react/chunks/{fr-CbvudRKC.mjs → fr-DkZpFQ1Q.mjs} +0 -0
  45. /package/dist/react/chunks/{hi-dKtSIE95.cjs → hi-B9TK87T8.cjs} +0 -0
  46. /package/dist/react/chunks/{hi-DrJIuj_0.mjs → hi-DrTcPkiY.mjs} +0 -0
  47. /package/dist/react/chunks/{ja-BtZsSYAE.mjs → ja-Dgahn--0.mjs} +0 -0
  48. /package/dist/react/chunks/{ja-6AwwCaS_.cjs → ja-LjzlAhAT.cjs} +0 -0
  49. /package/dist/react/chunks/{zh-BZsPG6yc.mjs → zh-BezRHDHs.mjs} +0 -0
  50. /package/dist/react/chunks/{zh-C6onHYpa.cjs → zh-CcodKi4U.cjs} +0 -0
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e}from"react/jsx-runtime";import{useRef as t,useState as n,useCallback as r,useEffect as i,useMemo as o,useContext as a,createContext as s}from"react";const c="__buildbaseBeforeLeave",d=globalThis,l=d[c]??(d[c]=new Set);const u="bb_attr",p=["gclid","gbraid","wbraid","dclid","fbclid","msclkid","li_fat_id","twclid","ttclid","rdt_cid","epik","irclickid","utm_source","utm_medium","utm_campaign","utm_term","utm_content","utm_id"],g=/^[\w.~-]{1,200}$/;function f(){return"undefined"==typeof window?null:window}function m(e,t){if(!e||!e.includes("."))return"";if(/^\d{1,3}(\.\d{1,3}){3}$/.test(e))return"";const n=t??f()?.document;if(!n)return"";const r=e.split(".");for(let e=r.length-2;e>=0;e--){const t="."+r.slice(e).join("."),i=`__bb_probe_${Date.now()}`;n.cookie=`${i}=1; domain=${t}; path=/; SameSite=Lax`;const o=n.cookie.includes(`${i}=1`);if(n.cookie=`${i}=; domain=${t}; path=/; max-age=0; SameSite=Lax`,o)return t}return""}function h(e){const t=e.cookie.split("; ").find(e=>e.startsWith(`${u}=`));if(!t)return{};try{const e=JSON.parse(decodeURIComponent(t.slice(8)));return"object"==typeof e&&e?e:{}}catch{return{}}}const y=p.filter(e=>!e.startsWith("utm_")),w=e=>y.some(t=>!!e[t]);function v(){const e=f();if(!e)return{};const t=e.document,n=h(t),r=function(e){const t=new URLSearchParams(e),n={};for(const e of p){const r=t.get(e);r&&(r.length>200||g.test(r)&&(n[e]=r))}return n}(e.location.search),i=Object.keys(r).length>0&&(w(r)||!w(n)),o=i?r:n;return 0===Object.keys(o).length?{}:(i&&!function(e,t){const n=new Set([...Object.keys(e),...Object.keys(t)]);for(const r of n)if(e[r]!==t[r])return!1;return!0}(r,n)&&function(e,t,n){const r=encodeURIComponent(JSON.stringify(t));e.cookie=`${u}=${r}; path=/; max-age=7776000; SameSite=Lax`+(n?`; domain=${n}`:"")}(t,o,m(e.location.hostname,t)),o)}function _(){const e=f();return e?h(e.document):{}}function k(e){try{const t=new URLSearchParams(e);return t.has("code")&&t.has("state")}catch{return!1}}const b="bb_pending_checkout";function I(){try{return"undefined"==typeof window?null:window.sessionStorage}catch{return null}}const C="bb_co";function $(){try{return"undefined"==typeof window?null:window.document??null}catch{return null}}function j(){const e=$();if(e)try{const t=m(window.location?.hostname??"",e);e.cookie=`${C}=; path=/; max-age=0; SameSite=Lax`+(t?`; domain=${t}`:"")}catch{}}function x(e,t){if(!e)return null;try{const n=JSON.parse(e);return n&&"string"==typeof n.eventId&&n.eventId?"number"!=typeof n.startedAt||t-n.startedAt>216e5?null:n:null}catch{return null}}function q(e=Date.now()){const t=I();if(!t)return null;let n=null;try{n=t.getItem(b),t.removeItem(b)}catch{return null}const r=x(n,e);return r&&j(),r}function A(e){try{return x(I()?.getItem(b)??null,e)}catch{return null}}function P(e,t=Date.now()){let n=null;try{n=new URLSearchParams(e).get("session_id")}catch{return null}if(!n)return null;const r=A(t);if(r?.sessionId===n)return q(t);const i=function(e){const t=$();if(!t||"string"!=typeof t.cookie)return null;const n=t.cookie.split("; ").find(e=>e.startsWith(`${C}=`));return n?x(decodeURIComponent(n.slice(6)),e):null}(t);return i?.sessionId!==n?null:(j(),i)}function S(e,t=Date.now()){return function(e){let t=null;try{t=new URLSearchParams(e).get("bb")}catch{return!1}if(!t)return!1;const n={};for(const e of t.split(",")){const t=e.indexOf(":");if(-1!==t)try{n[decodeURIComponent(e.slice(0,t))]=decodeURIComponent(e.slice(t+1))}catch{}}return"checkout"===n.action&&"cancel"===n.status}(e)&&A(t)?q(t):null}const O=new Set(["bif","clp","djf","gnf","jpy","kmf","krw","mga","pyg","rwf","ugx","vnd","vuv","xaf","xof","xpf"]),E=new Set(["bhd","jod","kwd","omr","tnd"]);function U(e,t){if("number"!=typeof e||!Number.isFinite(e))return;const n=(t??"").toLowerCase();return O.has(n)?e:e/(E.has(n)?1e3:100)}function L(){return"undefined"==typeof window?null:window}function T(e){const t=L();if(!t)return;t.gtag?.("consent","update",{ad_storage:e.marketing?"granted":"denied",ad_user_data:e.marketing?"granted":"denied",ad_personalization:e.marketing?"granted":"denied",analytics_storage:e.analytics?"granted":"denied"});const n=t.fbq;n?.("consent",e.marketing?"grant":"revoke")}const M={gtm:{title:"Google Tag Manager",vendor:"Google LLC",privacyUrl:"https://policies.google.com/privacy",idLabel:"Container ID",idPattern:"^GTM-[A-Z0-9]{4,10}$",idExample:"GTM-ABC1234",scriptOrigin:"https://www.googletagmanager.com",defaultConsentCategory:"analytics",supportsConsentMode:!0,needsConversionIds:!1},ga4:{title:"Google Analytics 4",vendor:"Google LLC",privacyUrl:"https://policies.google.com/privacy",idLabel:"Measurement ID",idPattern:"^G-[A-Z0-9]{8,12}$",idExample:"G-ABCD123456",scriptOrigin:"https://www.googletagmanager.com",defaultConsentCategory:"analytics",supportsConsentMode:!0,needsConversionIds:!1},google_ads:{title:"Google Ads",vendor:"Google LLC",privacyUrl:"https://policies.google.com/privacy",idLabel:"Conversion ID",idPattern:"^AW-[0-9]{9,12}$",idExample:"AW-123456789",scriptOrigin:"https://www.googletagmanager.com",defaultConsentCategory:"marketing",supportsConsentMode:!0,needsConversionIds:!0},meta_pixel:{title:"Meta Pixel",vendor:"Meta Platforms Ireland Limited",privacyUrl:"https://www.facebook.com/privacy/policy",idLabel:"Pixel ID",idPattern:"^[0-9]{15,16}$",idExample:"123456789012345",scriptOrigin:"https://connect.facebook.net",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!1,multiInstance:!0},x_pixel:{title:"X (Twitter) Pixel",vendor:"X Corp.",privacyUrl:"https://x.com/en/privacy",idLabel:"Pixel ID",idPattern:"^o[a-z0-9]{4,6}$",idExample:"o1a2b3",scriptOrigin:"https://static.ads-twitter.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!0,multiInstance:!0},linkedin:{title:"LinkedIn Insight Tag",vendor:"LinkedIn Ireland Unlimited Company",privacyUrl:"https://www.linkedin.com/legal/privacy-policy",idLabel:"Partner ID",idPattern:"^[0-9]{6,9}$",idExample:"1234567",scriptOrigin:"https://snap.licdn.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!0,multiInstance:!0},tiktok:{title:"TikTok Pixel",vendor:"TikTok Information Technologies UK Limited",privacyUrl:"https://www.tiktok.com/legal/privacy-policy",idLabel:"Pixel ID",idPattern:"^[A-Z0-9]{20}$",idExample:"C4A1B2C3D4E5F6G7H8I9",scriptOrigin:"https://analytics.tiktok.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!1,multiInstance:!0},reddit:{title:"Reddit Pixel",vendor:"Reddit, Inc.",privacyUrl:"https://www.reddit.com/policies/privacy-policy",idLabel:"Advertiser ID",idPattern:"^t2_[a-z0-9]{4,12}$",idExample:"t2_abc123",scriptOrigin:"https://www.redditstatic.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!1,multiInstance:!0},bing_uet:{title:"Microsoft Advertising (UET)",vendor:"Microsoft Corporation",privacyUrl:"https://privacy.microsoft.com/en-us/privacystatement",idLabel:"Tag ID",idPattern:"^[0-9]{7,9}$",idExample:"12345678",scriptOrigin:"https://bat.bing.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!1,multiInstance:!0},clarity:{title:"Microsoft Clarity",vendor:"Microsoft Corporation",privacyUrl:"https://privacy.microsoft.com/en-us/privacystatement",idLabel:"Project ID",idPattern:"^[a-z0-9]{10}$",idExample:"ab12cd34ef",scriptOrigin:"https://www.clarity.ms",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1},hotjar:{title:"Hotjar",vendor:"Hotjar Limited",privacyUrl:"https://www.hotjar.com/legal/policies/privacy/",idLabel:"Site ID",idPattern:"^[0-9]{6,9}$",idExample:"1234567",scriptOrigin:"https://static.hotjar.com",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1},posthog:{title:"PostHog",vendor:"PostHog, Inc.",privacyUrl:"https://posthog.com/privacy",idLabel:"Project API key",idPattern:"^phc_[A-Za-z0-9]{32,48}$",idExample:"phc_abcdefghijklmnopqrstuvwxyz012345",scriptOrigin:"https://us-assets.i.posthog.com",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1,hosts:["us.i.posthog.com","eu.i.posthog.com"]},plausible:{title:"Plausible Analytics",vendor:"Plausible Insights OÜ",privacyUrl:"https://plausible.io/privacy",idLabel:"Domain",idPattern:"^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$",idExample:"example.com",scriptOrigin:"https://plausible.io",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1},ahrefs:{title:"Ahrefs Analytics",vendor:"Ahrefs Pte. Ltd.",privacyUrl:"https://ahrefs.com/privacy",idLabel:"Analytics key",idPattern:"^[A-Za-z0-9+/=]{20,64}$",idExample:"AbCdEfGhIjKlMnOpQrStUv==",scriptOrigin:"https://analytics.ahrefs.com",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1}},D=Object.keys(M);function N(e){return"string"==typeof e&&Object.prototype.hasOwnProperty.call(M,e)}function B(e,t){return!!N(e)&&("string"==typeof t&&0!==t.length&&new RegExp(M[e].idPattern).test(t))}const R=/^[a-z][a-z0-9-]{0,40}$/,z=/^[\w.:/@+=-]{1,200}$/;function G(e){return function(e){if("string"!=typeof e)return!1;if(0===e.length||e.length>300)return!1;let t;try{t=new URL(e)}catch{return!1}return!("https:"!==t.protocol||!t.hostname||!t.hostname.includes(".")||e.includes("?")||e.includes("#")||t.username||t.password)}(e.src)&&function(e){if(null==e)return!0;if("object"!=typeof e||Array.isArray(e))return!1;const t=Object.entries(e);return!(t.length>12)&&t.every(([e,t])=>R.test(e)&&"string"==typeof t&&z.test(t))}(e.dataAttributes)}const V=Array.from(new Set(D.map(e=>M[e].scriptOrigin))).sort(),F={sign_up:{ga4:"sign_up",meta:"CompleteRegistration",tiktok:"CompleteRegistration",reddit:"SignUp"},login:{ga4:"login",meta:null,tiktok:null,reddit:null},trial_started:{ga4:"begin_checkout",meta:"StartTrial",tiktok:"StartTrial",reddit:"Lead"},checkout_started:{ga4:"begin_checkout",meta:"InitiateCheckout",tiktok:"InitiateCheckout",reddit:"AddToCart"},purchase:{ga4:"purchase",meta:"Purchase",tiktok:"CompletePayment",reddit:"Purchase"},subscription_created:{ga4:"purchase",meta:"Subscribe",tiktok:"Subscribe",reddit:"Purchase"},subscription_upgraded:{ga4:"subscription_upgraded",meta:null,tiktok:null,reddit:null},lead:{ga4:"generate_lead",meta:"Lead",tiktok:"SubmitForm",reddit:"Lead"},workspace_created:{ga4:"workspace_created",meta:null,tiktok:null,reddit:null}},H=Object.keys(F);function W(e){return H.includes(e)}function Z(){return"undefined"==typeof window?null:window}const J={gtm:"dataLayer",ga4:"gtag",google_ads:"gtag",meta_pixel:"fbq",x_pixel:"twq",linkedin:"lintrk",tiktok:"ttq",reddit:"rdt",bing_uet:"uetq",clarity:"clarity",hotjar:"hj",posthog:"posthog",plausible:"plausible",ahrefs:"__ahrefs_loaded"};function K(){return"undefined"==typeof window?null:window}function Q(e,t={}){const n=K();if(!n)return null;const r=n.document.createElement("script");r.async=!0,r.src=e;for(const[e,n]of Object.entries(t))r.setAttribute(e,n);return n.document.head.appendChild(r),r}function X(e){const t=K();if(!t)return;const n=t.document.createElement("script");n.text=e,t.document.head.appendChild(n)}function Y(e){const t=K();t&&(Array.isArray(t[e])||(t[e]=[]),"function"!=typeof t.gtag&&(t.gtag=function(){t[e].push(arguments)}))}const ee=new Set;function te(e){for(const t of ee)if(t.slice(0,t.indexOf(":"))===e)return!0;return!1}function ne(e,t){const n=K();if(!n)return!1;if("gtm"===e||"ga4"===e||"google_ads"===e){const e=n.google_tag_manager;return!(!e||"object"!=typeof e)&&Object.prototype.hasOwnProperty.call(e,t)}const r=J[e];if(!r)return!1;if(void 0===n[r])return!1;if(ee.has(`${e}:${t}`))return!0;return!M[e].multiInstance||!te(e)}const re={meta_pixel:e=>`fbq('init','${e}');fbq('track','PageView');`,x_pixel:e=>`twq('config','${e}');`,tiktok:e=>`ttq.load('${e}');ttq.page();`,reddit:e=>`rdt('init','${e}');rdt('track','PageVisit');`,bing_uet:e=>`window.uetq=window.uetq||[];window.uetq.push({ti:'${e}',enableAutoSpaTracking:false});`,linkedin:e=>`window._linkedin_data_partner_ids=window._linkedin_data_partner_ids||[];window._linkedin_data_partner_ids.push('${e}');`};function ie(e,t,n){const r=function(e,t,n){const r=K();if(!r)return!1;if("external"===e.provider){if(!e.src)return!1;const t={};for(const[n,r]of Object.entries(e.dataAttributes??{}))t[`data-${n}`]=r;return Q(e.src,t),!0}const i=e.provider,o=M[i];if(!o)return!1;const a=e.providerId;if(!a)return!1;const s=re[i];if(s&&te(i))return X(s(a)),!0;switch(i){case"gtm":{Y(t),r[t].push({"gtm.start":Date.now(),event:"gtm.js"});const e="dataLayer"===t?"":`&l=${t}`;return Q(`${o.scriptOrigin}/gtm.js?id=${a}${e}`),!0}case"ga4":case"google_ads":{Y(t),Q(`${o.scriptOrigin}/gtag/js?id=${a}`);const e=r.gtag;e("js",new Date);const s="ga4"===i&&n?.gaClientId?{client_id:n.gaClientId}:void 0;return s?e("config",a,s):e("config",a),!0}case"meta_pixel":return X(`!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,document,'script','${o.scriptOrigin}/en_US/fbevents.js');fbq('init','${a}');fbq('track','PageView');`),!0;case"x_pixel":return X(`!function(e,t,n,s,u,a){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments)},s.version='1.1',s.queue=[],u=t.createElement(n),u.async=!0,u.src='${o.scriptOrigin}/uwt.js',a=t.getElementsByTagName(n)[0],a.parentNode.insertBefore(u,a))}(window,document,'script');twq('config','${a}');`),!0;case"linkedin":return X(`window._linkedin_partner_id='${a}';window._linkedin_data_partner_ids=window._linkedin_data_partner_ids||[];window._linkedin_data_partner_ids.push('${a}');window.lintrk=window.lintrk||function(a,b){(window.lintrk.q=window.lintrk.q||[]).push([a,b])};window.lintrk.q=window.lintrk.q||[];`),Q(`${o.scriptOrigin}/li.lms-analytics/insight.min.js`),!0;case"tiktok":return X(`!function(w,d,t){w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=['page','track','identify','instances','debug','on','off','once','ready','alias','group','enableCookie','disableCookie'];ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.load=function(e,n){var r='${o.scriptOrigin}/i18n/pixel/events.js';ttq._i=ttq._i||{};ttq._i[e]=[];ttq._i[e]._u=r;ttq._t=ttq._t||{};ttq._t[e]=+new Date;ttq._o=ttq._o||{};ttq._o[e]=n||{};var o=d.createElement('script');o.type='text/javascript';o.async=!0;o.src=r+'?sdkid='+e+'&lib='+t;var a=d.getElementsByTagName('script')[0];a.parentNode.insertBefore(o,a)};ttq.load('${a}');ttq.page()}(window,document,'ttq');`),!0;case"reddit":return X(`!function(w,d){if(!w.rdt){var p=w.rdt=function(){p.sendEvent?p.sendEvent.apply(p,arguments):p.callQueue.push(arguments)};p.callQueue=[];var t=d.createElement('script');t.src='${o.scriptOrigin}/ads/pixel.js';t.async=!0;var s=d.getElementsByTagName('script')[0];s.parentNode.insertBefore(t,s)}}(window,document);rdt('init','${a}');rdt('track','PageVisit');`),!0;case"bing_uet":return X(`(function(w,d,t,r,u){w[u]=w[u]||[];w[u].push({ti:'${a}',enableAutoSpaTracking:false});var o=d.createElement(t);o.src='${o.scriptOrigin}/bat.js';o.async=1;var i=d.getElementsByTagName(t)[0];i.parentNode.insertBefore(o,i)})(window,document,'script',0,'uetq');`),!0;case"clarity":return X(`(function(c,l,a,r,i,t,y){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};t=l.createElement(r);t.async=1;t.src='${o.scriptOrigin}/tag/'+i;y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y)})(window,document,'clarity','script','${a}');`),!0;case"hotjar":return X(`(function(h,o,t,j,a,r){h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};h._hjSettings={hjid:${a},hjsv:6};a=o.getElementsByTagName('head')[0];r=o.createElement('script');r.async=1;r.src='${o.scriptOrigin}/hotjar-'+h._hjSettings.hjid+'.js?sv='+h._hjSettings.hjsv;a.appendChild(r)})(window,document);`),!0;case"posthog":{const t=o.hosts,n=t?.includes(e.host??"")?e.host:t?.[0]??"us.i.posthog.com";return X(`!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split('.');2==o.length&&(t=t[o[0]],e=o[1]);t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement('script')).type='text/javascript',p.async=!0,p.src='${o.scriptOrigin}/static/array.js',(r=t.getElementsByTagName('script')[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a='posthog',u.people=u.people||[],u.toString=function(t){var e='posthog';return'posthog'!==a&&(e+='.'+a),t||(e+=' (stub)'),e},u.people.toString=function(){return u.toString(1)+'.people (stub)'},o='init capture register register_once identify alias people.set people.set_once set_config get_distinct_id getFeatureFlag isFeatureEnabled onFeatureFlags reloadFeatureFlags group reset'.split(' '),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);posthog.init('${a}',{api_host:'https://${n}'});`),!0}case"plausible":return X("window.plausible=window.plausible||function(){(window.plausible.q=window.plausible.q||[]).push(arguments)};"),Q(`${o.scriptOrigin}/js/script.js`,{"data-domain":a,defer:"true"}),!0;case"ahrefs":return Q(`${o.scriptOrigin}/analytics.js`,{"data-key":a}),r.__ahrefs_loaded=!0,!0;default:return!1}}(e,t,n);return r&&"external"!==e.provider&&e.providerId&&ee.add(`${e.provider}:${e.providerId}`),r}const oe=Symbol.for("@buildbase/sdk.tracking.context"),ae=globalThis,se=ae[oe]??(ae[oe]=s(null)),ce={consent:{manifest:[],state:null,set:()=>{}},track:()=>{},setUser:()=>{},setProperties:()=>{},getProperties:()=>({}),completeCheckout:async()=>{},installed:{},ready:!0,attribution:{}};function de(){return a(se)??ce}const le=({serverUrl:a,orgId:s,clientId:c,enabled:d=!0,consent:u="auto",autoPageview:p=!0,events:g,onEvent:f,properties:m,enrich:h,identity:y,debug:w=!1,children:_})=>{const b=t(y);b.current=y;const[I,C]=n(null),[$,j]=n(!1),[x,q]=n(!1),A="granted"===u?{analytics:!0,marketing:!0}:"denied"===u?{analytics:!1,marketing:!1}:null,[O,E]=n(A),D=t(null),R=t(f);R.current=f;const z=t(h);z.current=h;const V=t({});V.current=m??{};const H=t({}),J=r(()=>({...V.current,...H.current}),[]),K=r(e=>{const t={...H.current,...e};for(const[e,n]of Object.entries(t))void 0===n&&delete t[e];H.current=t},[]),[Q,X]=n({}),ee=t({}),[te,re]=n(0),oe=I?.dataLayerName??"dataLayer",ae=r((...e)=>{w&&console.info("[buildbase:tracking]",...e)},[w]);i(()=>{return e=()=>{0!==Object.keys(ee.current).length&&window.dispatchEvent("function"==typeof PageTransitionEvent?new PageTransitionEvent("pagehide",{persisted:!1}):new Event("pagehide"))},l.add(e),()=>{l.delete(e)};var e},[]),i(()=>{if(!(d&&a&&s&&c))return void j(!0);let e=!1;const t=`${a.replace(/\/$/,"")}/api/v1/public/${s}/tracking?clientId=${encodeURIComponent(c)}`;return fetch(t).then(e=>e.ok?e.json():null).then(t=>{if(e||!t)return;const n=t.data??t;n&&Array.isArray(n.scripts)&&C(n)}).catch(()=>{ae("config fetch failed; nothing installed")}).finally(()=>{e||j(!0)}),()=>{e=!0}},[d,a,s,c,ae]),i(()=>{d&&X(v())},[d]),i(()=>{d&&I?.enabled&&(Y(oe),function(e,t){const n=L();if(!n)return;Array.isArray(n[e])||(n[e]=[]),"function"!=typeof n.gtag&&(n.gtag=function(){n[e].push(arguments)});const r="granted"===t?"granted":"denied";n.gtag("consent","default",{ad_storage:r,ad_user_data:r,ad_personalization:r,analytics_storage:r,wait_for_update:500})}(oe,u),D.current&&T(D.current))},[d,I?.enabled,oe,u]);const ce=o(()=>I?.enabled?I.scripts.filter(e=>{const t=N(e.provider)&&M[e.provider].supportsConsentMode;return function(e,t,n,r){return"denied"!==r&&("granted"===r||(n?"marketing"===e?n.marketing:n.analytics:t&&"analytics"===e))}(e.consentCategory,t,O,u)}):[],[I,O,u]),[de,le]=n(()=>"undefined"==typeof window||!k(window.location.search));i(()=>{if(de)return;const e=setInterval(()=>{k(window.location.search)||le(!0)},50),t=setTimeout(()=>le(!0),5e3);return()=>{clearInterval(e),clearTimeout(t)}},[de]),i(()=>{if(!de)return;if(!d||!I?.enabled)return void($&&q(!0));let e=0;for(const t of ce)if(!ee.current[t.key]){if("external"===t.provider){if(!G({src:t.src,dataAttributes:t.dataAttributes})){ae("rejected external script",t.key);continue}}else{if(!N(t.provider)){ae("rejected unknown provider",t.provider);continue}if(!B(t.provider,t.providerId)){ae("rejected id for",t.provider);continue}if(ne(t.provider,t.providerId??"")){ae(`${t.provider} ${t.providerId} is already on the page; skipping. Configure each tag in exactly one place.`);continue}}ie(t,oe,b.current)&&(ee.current[t.key]=t.providerId??t.src??"",e+=1,ae("installed",t.key))}e&&re(e=>e+1);const t=window;t.__buildbase=t.__buildbase??{},t.__buildbase.tracking={installed:{...ee.current},dataLayerName:oe,clientId:c};const n=Object.keys(ee.current).length>0,r=null!==O||0===I.scripts.length;(n||r)&&q(!0)},[d,I,ce,$,O,oe,ae,de,c]),i(()=>{if(!d||!p||!I?.enabled)return;if("undefined"==typeof window)return;if(!de)return;let e=null;const t=()=>{e&&clearTimeout(e),e=setTimeout(()=>function(e,t){const n=Z();if(!n)return;const r=n[t];Array.isArray(r)&&r.push({event:"page_view",page_path:n.location.pathname,page_location:n.location.href,page_title:n.document.title});for(const t of e)switch(t.provider){case"ga4":n.gtag?.("event","page_view",{send_to:t.providerId,page_path:n.location.pathname,page_location:n.location.href,page_title:n.document.title});break;case"meta_pixel":n.fbq?.("track","PageView");break;case"tiktok":{const e=n.ttq;e?.page?.();break}case"reddit":n.rdt?.("track","PageVisit")}}(ce,oe),50)},n=window.history,r=n.pushState,i=n.replaceState;return n.pushState=function(...e){const n=r.apply(this,e);return t(),n},n.replaceState=function(...e){const n=i.apply(this,e);return t(),n},window.addEventListener("popstate",t),()=>{n.pushState=r,n.replaceState=i,window.removeEventListener("popstate",t),e&&clearTimeout(e)}},[d,p,I?.enabled,ce,oe,de]),i(()=>{if(!d)return;const e=function(e,t){const n=e?.mode??"auto",r=e?.overrides??{};if(("manual"===n||Object.values(r).some(e=>"manual"===e))&&!t)return'[buildbase:tracking] events are set to "manual" but no onEvent handler was provided, so those events would never fire anywhere. Pass onEvent, or use mode "auto".';for(const e of Object.keys(r))if(!W(e))return`[buildbase:tracking] unknown event "${e}" in events.overrides. Overrides only apply to the events the SDK fires itself.`;return null}(g,!!f);if(e)throw new Error(e)},[d,g,f]);const ue=r((e,t={},n)=>{if(!d)return;const r=n?.eventId||function(){const e=globalThis.crypto;return e?.randomUUID?e.randomUUID():`${Date.now().toString(16)}-${Math.random().toString(16).slice(2,10)}`}(),i=g?.mode??"auto",o=(W(e)?g?.overrides?.[e]:void 0)??i,a={...V.current,...H.current,...Q,...t},s=z.current?.({name:e,params:a})??{},c={...a,...s},l=R.current?.({name:e,params:c,eventId:r,handledBy:o});"manual"!==o&&!0!==l?(!function(e,t,n,r,i){const o=Z();if(!o)return;const a=o[i];Array.isArray(a)&&a.push({event:e,...t,event_id:n});const s=W(e)?F[e]:{ga4:e,meta:null,tiktok:null,reddit:null};for(const i of r){const r=i.provider,a=M[r];if(a){if(a.needsConversionIds){const a=i.conversionIds?.[e];if(!a)continue;"google_ads"===r?o.gtag?.("event","conversion",{send_to:`${i.providerId}/${a}`,transaction_id:n,...t}):"x_pixel"===r?o.twq?.("event",a,{...t,conversion_id:n}):"linkedin"===r&&o.lintrk?.("track",{conversion_id:a});continue}switch(r){case"ga4":s.ga4&&o.gtag?.("event",s.ga4,{...t,send_to:i.providerId,event_id:n});break;case"meta_pixel":s.meta&&o.fbq?.("track",s.meta,t,{eventID:n});break;case"tiktok":if(s.tiktok){const e=o.ttq;e?.track?.(s.tiktok,{...t,event_id:n})}break;case"reddit":s.reddit&&o.rdt?.("track",s.reddit,{...t,conversionId:n});break;case"bing_uet":{const r=o.uetq;r?.push?.("event",s.ga4??e,{...t,event_id:n});break}case"clarity":o.clarity?.("event",e);break;case"hotjar":{const t=o.hj;t?.("event",e);break}case"posthog":{const r=o.posthog;r?.capture?.(e,{...t,event_id:n});break}case"plausible":o.plausible?.(e,{props:t})}}}}(e,c,r,ce,oe),ae("event fired:",e,r)):ae("event handled by app:",e)},[d,g,ce,oe,Q,ae]),pe=r(async(e,t={})=>{const n=function(e){return{name:"trial_started"===e.kind?"trial_started":"purchase",params:{...e.workspaceId?{workspace_id:e.workspaceId}:{},...e.planVersionId?{plan_version_id:e.planVersionId}:{},...e.creditPackageId?{credit_package_id:e.creditPackageId}:{},...e.billingInterval?{billing_interval:e.billingInterval}:{},...e.currency?{currency:e.currency.toUpperCase()}:{},..."number"==typeof e.value?{value:e.value}:{},...e.sessionId?{transaction_id:e.sessionId}:{}}}}(e);let r=n.params;if(e.sessionId&&a&&s){const t=await async function(e,t){try{const n=e.serverUrl.replace(/\/$/,""),r=await fetch(`${n}/api/v1/public/${encodeURIComponent(e.orgId)}/checkout/${encodeURIComponent(t)}`,{credentials:"omit",..."undefined"!=typeof AbortSignal&&AbortSignal.timeout?{signal:AbortSignal.timeout(2e3)}:{}});if(!r.ok)return null;const i=await r.json(),o=i?.data??i;return"number"!=typeof o?.amount?null:{value:U(o.amount,o.currency),currency:"string"==typeof o.currency?o.currency:void 0,...Array.isArray(o.items)&&o.items.length?{items:o.items}:{}}}catch{return null}}({serverUrl:a,orgId:s},e.sessionId);t&&"number"==typeof t.value&&(r={...r,value:t.value,...t.currency?{currency:t.currency.toUpperCase()}:{},...t.items?.length?{items:t.items}:{}})}if(ue(n.name,{...r,...t},{eventId:e.eventId}),"purchase"===n.name&&e.sessionId&&a&&s){const t=(I?.scripts??[]).find(e=>"ga4"===e.provider&&e.providerId);t&&ne("ga4",t.providerId??"")&&function(e,t,n){try{const r=e.serverUrl.replace(/\/$/,"");fetch(`${r}/api/v1/public/${encodeURIComponent(e.orgId)}/checkout/${encodeURIComponent(t)}/reported`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:n}),keepalive:!0,credentials:"omit"}).catch(()=>{})}catch{}}({serverUrl:a,orgId:s},e.sessionId,"ga4")}},[a,s,ue,I]),[ge]=n(()=>"undefined"==typeof window?"":window.location.search);i(()=>{if(!d||!x)return;if("undefined"==typeof window)return;const e=P(window.location.search);if(e)return void pe(e);const t=S(ge);t&&ue("checkout_abandoned",{...t.workspaceId?{workspace_id:t.workspaceId}:{},...t.planVersionId?{plan_version_id:t.planVersionId}:{},...t.creditPackageId?{credit_package_id:t.creditPackageId}:{},...t.billingInterval?{billing_interval:t.billingInterval}:{},...t.currency?{currency:t.currency.toUpperCase()}:{},..."number"==typeof t.value?{value:t.value}:{},seconds_at_checkout:Math.max(0,Math.round((Date.now()-t.startedAt)/1e3))})},[d,x,pe,ge,ue]);const fe=r(e=>{D.current=e,E(e),T(e)},[]),me=r((e,t)=>function(e,t,n){const r=Z();if(!r)return;const i=!!n&&Object.keys(n).length>0;for(const o of t)switch(o.provider){case"ga4":case"google_ads":r.gtag?.("set",{user_id:e}),i&&r.gtag?.("set",{user_properties:n});break;case"meta_pixel":o.providerId&&r.fbq?.("init",o.providerId,{external_id:e});break;case"posthog":r.posthog?.identify?.(e,i?n:void 0);break;case"clarity":if(r.clarity?.("identify",e),i)for(const[e,t]of Object.entries(n))r.clarity?.("set",e,String(t));break;case"hotjar":r.hj?.("identify",e,{});break;case"tiktok":{const t=r.ttq;t?.identify?.({external_id:e});break}}}(e,ce,t),[ce]),he=o(()=>({consent:{manifest:I?.consent?.manifest??[],state:O,set:fe},track:ue,setUser:me,setProperties:K,getProperties:J,completeCheckout:pe,installed:{...ee.current},ready:x,attribution:Q}),[I,O,fe,ue,me,K,J,pe,x,te,Q]);return e(se.Provider,{value:he,children:_})};function ue(e={}){const{completeCheckout:n,ready:r}=de(),o=t(e);o.current=e;const a=t(!1);i(()=>{if(!r)return;if(a.current)return;const e=P(window.location.search)??q();e&&(a.current=!0,n(e,o.current))},[r,n])}le.displayName="BuildBaseTracking";const pe={sign_in_started:"The sign-in / sign-up button was pressed.",pricing_viewed:"A <PricingPage> finished loading its plans.",pricing_plan_selected:"A plan was chosen on a <PricingPage>.",workspace_switcher_opened:"The workspace switcher was opened.",workspace_settings_opened:"The workspace settings modal was opened.",workspace_settings_section_viewed:"A different section of the settings modal was opened.",plan_picker_opened:"The plan picker was shown.",billing_interval_changed:"Monthly / quarterly / yearly was switched in the plan picker.",plan_selected:"A plan was chosen in the plan picker.",plan_picker_dismissed:"The plan picker was closed without choosing a plan.",checkout_abandoned:"The customer came back from Stripe without paying.",billing_portal_opened:"Stripe’s billing portal was opened.",subscription_cancel_started:"The cancel-subscription confirmation was opened.",subscription_cancelled:"A subscription was cancelled.",subscription_resumed:"A cancelled subscription was resumed.",feature_gate_shown:'A feature gate rendered its "not on your plan" side.',quota_limit_reached:"A quota gate rendered because a quota is used up.",quota_threshold_reached:"A usage-threshold gate rendered.",plan_gate_shown:'A plan gate rendered its "needs another plan" side.',subscription_notice_shown:"A billing notice (trial ending, payment failed…) was shown.",sdk_error:"An SDK operation failed (component, action and code only)."};export{p as ATTRIBUTION_PARAMS,le as BuildBaseTracking,F as EVENT_MAPPINGS,pe as FUNNEL_EVENTS,M as TAG_PROVIDERS,D as TAG_PROVIDER_IDS,V as TAG_SCRIPT_ORIGINS,v as captureAttribution,_ as getAttribution,W as isCanonicalEvent,N as isTagProviderId,B as isValidProviderId,ue as useCheckoutCompleted,de as useTracking};
2
+ import{jsx as e}from"react/jsx-runtime";import{useRef as t,useState as n,useMemo as r,useCallback as i,useEffect as o,useContext as a,createContext as s}from"react";const c="__buildbaseBeforeLeave",d=globalThis,l=d[c]??(d[c]=new Set);const u="bb_attr",p=["gclid","gbraid","wbraid","dclid","fbclid","msclkid","li_fat_id","twclid","ttclid","rdt_cid","epik","irclickid","utm_source","utm_medium","utm_campaign","utm_term","utm_content","utm_id"],g=/^[\w.~-]{1,200}$/;function f(){return"undefined"==typeof window?null:window}function m(e,t){if(!e||!e.includes("."))return"";if(/^\d{1,3}(\.\d{1,3}){3}$/.test(e))return"";const n=t??f()?.document;if(!n)return"";const r=e.split(".");for(let e=r.length-2;e>=0;e--){const t="."+r.slice(e).join("."),i=`__bb_probe_${Date.now()}`;n.cookie=`${i}=1; domain=${t}; path=/; SameSite=Lax`;const o=n.cookie.includes(`${i}=1`);if(n.cookie=`${i}=; domain=${t}; path=/; max-age=0; SameSite=Lax`,o)return t}return""}const h="$t",y="$l";function w(e){return function(e){const t=e.cookie.split("; ").find(e=>e.startsWith(`${u}=`));if(!t)return{params:{}};try{const e=JSON.parse(decodeURIComponent(t.slice(8)));if("object"!=typeof e||!e)return{params:{}};const{[h]:n,[y]:r,...i}=e;return{params:i,..."number"==typeof n&&n>0?{capturedAt:n}:{},..."string"==typeof r&&r?{landingUrl:r}:{}}}catch{return{params:{}}}}(e).params}function v(e){try{const{origin:t,pathname:n}=e.location;return t&&"null"!==t?`${t}${n}`.slice(0,300):void 0}catch{return}}const _=p.filter(e=>!e.startsWith("utm_")),b=e=>_.some(t=>!!e[t]);function k(){const e=f();if(!e)return{};const t=e.document,n=w(t),r=function(e){const t=new URLSearchParams(e),n={};for(const e of p){const r=t.get(e);r&&(r.length>200||g.test(r)&&(n[e]=r))}return n}(e.location.search),i=Object.keys(r).length>0&&(b(r)||!b(n)),o=i?r:n;return 0===Object.keys(o).length?{}:(i&&!function(e,t){const n=new Set([...Object.keys(e),...Object.keys(t)]);for(const r of n)if(e[r]!==t[r])return!1;return!0}(r,n)&&function(e,t,n,r){const i=encodeURIComponent(JSON.stringify({...t,[h]:r.capturedAt,...r.landingUrl?{[y]:r.landingUrl}:{}}));e.cookie=`${u}=${i}; path=/; max-age=7776000; SameSite=Lax`+(n?`; domain=${n}`:"")}(t,o,m(e.location.hostname,t),{capturedAt:Date.now(),landingUrl:v(e)}),o)}function I(){const e=f();return e?w(e.document):{}}function C(e){try{const t=new URLSearchParams(e);return t.has("code")&&t.has("state")}catch{return!1}}const $="bb_pending_checkout";function S(){try{return"undefined"==typeof window?null:window.sessionStorage}catch{return null}}const A="bb_co";function j(){try{return"undefined"==typeof window?null:window.document??null}catch{return null}}function x(){const e=j();if(e)try{const t=m(window.location?.hostname??"",e);e.cookie=`${A}=; path=/; max-age=0; SameSite=Lax`+(t?`; domain=${t}`:"")}catch{}}function q(e,t){if(!e)return null;try{const n=JSON.parse(e);return n&&"string"==typeof n.eventId&&n.eventId?"number"!=typeof n.startedAt||t-n.startedAt>216e5?null:n:null}catch{return null}}function U(e=Date.now()){const t=S();if(!t)return null;let n=null;try{n=t.getItem($),t.removeItem($)}catch{return null}const r=q(n,e);return r&&x(),r}function O(e){try{return q(S()?.getItem($)??null,e)}catch{return null}}function P(e,t=Date.now()){let n=null;try{n=new URLSearchParams(e).get("session_id")}catch{return null}if(!n)return null;const r=O(t);if(r?.sessionId===n)return U(t);const i=function(e){const t=j();if(!t||"string"!=typeof t.cookie)return null;const n=t.cookie.split("; ").find(e=>e.startsWith(`${A}=`));return n?q(decodeURIComponent(n.slice(6)),e):null}(t);return i?.sessionId!==n?null:(x(),i)}function E(e,t=Date.now()){return function(e){let t=null;try{t=new URLSearchParams(e).get("bb")}catch{return!1}if(!t)return!1;const n={};for(const e of t.split(",")){const t=e.indexOf(":");if(-1!==t)try{n[decodeURIComponent(e.slice(0,t))]=decodeURIComponent(e.slice(t+1))}catch{}}return"checkout"===n.action&&"cancel"===n.status}(e)&&O(t)?U(t):null}const T=new Set(["bif","clp","djf","gnf","jpy","kmf","krw","mga","pyg","rwf","ugx","vnd","vuv","xaf","xof","xpf"]),L=new Set(["bhd","jod","kwd","omr","tnd"]);function D(e,t){if("number"!=typeof e||!Number.isFinite(e))return;const n=(t??"").toLowerCase();return T.has(n)?e:e/(L.has(n)?1e3:100)}const M=["AT","BE","BG","HR","CY","CZ","DK","EE","FI","FR","DE","GR","HU","IE","IT","LV","LT","LU","MT","NL","PL","PT","RO","SK","SI","ES","SE","IS","LI","NO"],N={default:"granted",regions:{denied:["EEA","GB","CH"]}},R=/^[A-Z]{2}(-[A-Z0-9]{1,3})?$/;function B(e){const t=new Set;for(const n of e??[]){const e=String(n).trim().toUpperCase();if("EEA"===e)for(const e of M)t.add(e);else R.test(e)&&t.add(e)}return[...t]}function H(e,t,n){return e.includes(t)}function V(e,t,n){const r=(t??"").trim().toUpperCase();if(!/^[A-Z]{2}$/.test(r)||"XX"===r||"T1"===r)return"denied";const i=(n??"").trim().toUpperCase()||void 0,o=B(e.regions?.denied),a=B(e.regions?.granted);if(i){if(o.includes(`${r}-${i}`))return"denied";if(a.includes(`${r}-${i}`))return"granted"}return H(o,r)?"denied":H(a,r)||"granted"===e.default?"granted":"denied"}function z(){return"undefined"==typeof window?null:window}const G=["ad_storage","ad_user_data","ad_personalization","analytics_storage"];function F(e){const t={};for(const n of G)t[n]=e;return t}function J(e){const t=z();if(!t)return;const n=t.gtag;n?.("consent","update",{ad_storage:e.marketing?"granted":"denied",ad_user_data:e.marketing?"granted":"denied",ad_personalization:e.marketing?"granted":"denied",analytics_storage:e.analytics?"granted":"denied"}),n?.("set","ads_data_redaction",!e.marketing);const r=t.fbq;r?.("consent",e.marketing?"grant":"revoke")}const Z="bb_cid";function W(){if("undefined"!=typeof document&&"undefined"!=typeof window)try{const e=document.cookie.split("; ").find(e=>e.startsWith(`${Z}=`)),t=e?.slice(7);if(t&&/^[\w-]{16,64}$/.test(t))return t;const n=function(){const e=globalThis.crypto;if(e&&"function"==typeof e.randomUUID)return e.randomUUID();const t=new Uint8Array(16);if(e&&"function"==typeof e.getRandomValues)e.getRandomValues(t);else for(let e=0;e<t.length;e++)t[e]=Math.floor(256*Math.random());return Array.from(t).map(e=>e.toString(16).padStart(2,"0")).join("")}(),r=m(window.location.hostname,document);return document.cookie=`${Z}=${n}; path=/; max-age=34128000; SameSite=Lax`+(r?`; domain=${r}`:""),n}catch{return}}const K="bb_consent_recorded";function X(e){if("function"!=typeof fetch||!e.serverUrl||!e.orgId||!e.clientId)return;const t=JSON.stringify([e.orgId,e.clientId,!!e.state.analytics,!!e.state.marketing,e.manifestVersion??"",e.consentString??"",e.headers?.["x-session-id"]?"account":"anonymous"]);if(!e.source&&function(e){try{return window.localStorage.getItem(K)===e}catch{return!1}}(t))return;!function(e){try{window.localStorage.setItem(K,e)}catch{}}(t);const n=W();if(!n)return;const r=`${e.serverUrl.replace(/\/$/,"")}/api/v1/public/${e.orgId}/consent`;try{fetch(r,{method:"POST",keepalive:!0,headers:{"content-type":"application/json",...e.headers??{}},body:JSON.stringify({clientId:e.clientId,visitorId:n,choices:{analytics:!!e.state.analytics,marketing:!!e.state.marketing},...e.manifestVersion?{manifestVersion:e.manifestVersion}:{},...e.source?{source:e.source.slice(0,40)}:{},...e.consentString?{consentString:e.consentString.slice(0,2e3)}:{}})}).catch(()=>{})}catch{}}const Q=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),Y=(e,t)=>e>>>t|e<<32-t;function ee(e){return function(e){let t="";for(let n=0;n<e.length;n++)t+=e[n].toString(16).padStart(2,"0");return t}(function(e){let t=1779033703,n=3144134277,r=1013904242,i=2773480762,o=1359893119,a=2600822924,s=528734635,c=1541459225;const d=e.length,l=d+1,u=l+(56-l%64+64)%64+8,p=new Uint8Array(u);p.set(e,0),p[d]=128;const g=8*d,f=Math.floor(g/4294967296),m=g>>>0;p[u-8]=f>>>24&255,p[u-7]=f>>>16&255,p[u-6]=f>>>8&255,p[u-5]=255&f,p[u-4]=m>>>24&255,p[u-3]=m>>>16&255,p[u-2]=m>>>8&255,p[u-1]=255&m;const h=new Uint32Array(64);for(let e=0;e<u;e+=64){for(let t=0;t<16;t++){const n=e+4*t;h[t]=p[n]<<24|p[n+1]<<16|p[n+2]<<8|p[n+3]}for(let e=16;e<64;e++){const t=Y(h[e-15],7)^Y(h[e-15],18)^h[e-15]>>>3,n=Y(h[e-2],17)^Y(h[e-2],19)^h[e-2]>>>10;h[e]=h[e-16]+t+h[e-7]+n>>>0}let d=t,l=n,u=r,g=i,f=o,m=a,y=s,w=c;for(let e=0;e<64;e++){const t=w+(Y(f,6)^Y(f,11)^Y(f,25))+(f&m^~f&y)+Q[e]+h[e]>>>0,n=d&l^d&u^l&u;w=y,y=m,m=f,f=g+t>>>0,g=u,u=l,l=d,d=t+((Y(d,2)^Y(d,13)^Y(d,22))+n>>>0)>>>0}t=t+d>>>0,n=n+l>>>0,r=r+u>>>0,i=i+g>>>0,o=o+f>>>0,a=a+m>>>0,s=s+y>>>0,c=c+w>>>0}const y=new Uint8Array(32),w=[t,n,r,i,o,a,s,c];for(let e=0;e<8;e++)y[4*e]=w[e]>>>24&255,y[4*e+1]=w[e]>>>16&255,y[4*e+2]=w[e]>>>8&255,y[4*e+3]=255&w[e];return y}(e))}function te(e){const t=String(e??"").trim().toLowerCase(),n=t.lastIndexOf("@");if(n<1||n===t.length-1)return"";let r=t.slice(0,n);const i=t.slice(n+1);return"gmail.com"!==i&&"googlemail.com"!==i||(r=r.replace(/\./g,"")),`${r}@${i}`}function ne(e){const t=String(e??"").trim();if(!t.startsWith("+"))return"";const n=t.replace(/[^\d]/g,"");return n.length>=8&&n.length<=15?`+${n}`:""}async function re(e){const t=globalThis.crypto?.subtle;if(t&&"function"==typeof t.digest)try{const n=await t.digest("SHA-256",(new TextEncoder).encode(e));return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,"0")).join("")}catch{}return ee((n=e,(new TextEncoder).encode(n)));var n}async function ie(e){const t=te(e.email),n=ne(e.phone),r={};return t&&(r.emailHash=await re(t)),n&&(r.phoneHash=await re(n)),r}function oe(e,t){if("undefined"==typeof window)return;if(!t.emailHash&&!t.phoneHash)return;const n=window;e.some(e=>"google_ads"===e.provider||"ga4"===e.provider||"gtm"===e.provider)&&n.gtag?.("set","user_data",{...t.emailHash?{sha256_email_address:t.emailHash}:{},...t.phoneHash?{sha256_phone_number:t.phoneHash}:{}});for(const r of e)"meta_pixel"===r.provider&&r.providerId&&n.fbq?.("init",r.providerId,{...t.emailHash?{em:t.emailHash}:{},...t.phoneHash?{ph:t.phoneHash}:{}})}const ae={gtm:{title:"Google Tag Manager",vendor:"Google LLC",privacyUrl:"https://policies.google.com/privacy",idLabel:"Container ID",idPattern:"^GTM-[A-Z0-9]{4,10}$",idExample:"GTM-ABC1234",scriptOrigin:"https://www.googletagmanager.com",defaultConsentCategory:"analytics",supportsConsentMode:!0,needsConversionIds:!1},ga4:{title:"Google Analytics 4",vendor:"Google LLC",privacyUrl:"https://policies.google.com/privacy",idLabel:"Measurement ID",idPattern:"^G-[A-Z0-9]{8,12}$",idExample:"G-ABCD123456",scriptOrigin:"https://www.googletagmanager.com",defaultConsentCategory:"analytics",supportsConsentMode:!0,needsConversionIds:!1},google_ads:{title:"Google Ads",vendor:"Google LLC",privacyUrl:"https://policies.google.com/privacy",idLabel:"Conversion ID",idPattern:"^AW-[0-9]{9,12}$",idExample:"AW-123456789",scriptOrigin:"https://www.googletagmanager.com",defaultConsentCategory:"marketing",supportsConsentMode:!0,needsConversionIds:!0},meta_pixel:{title:"Meta Pixel",vendor:"Meta Platforms Ireland Limited",privacyUrl:"https://www.facebook.com/privacy/policy",idLabel:"Pixel ID",idPattern:"^[0-9]{15,16}$",idExample:"123456789012345",scriptOrigin:"https://connect.facebook.net",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!1,multiInstance:!0},x_pixel:{title:"X (Twitter) Pixel",vendor:"X Corp.",privacyUrl:"https://x.com/en/privacy",idLabel:"Pixel ID",idPattern:"^o[a-z0-9]{4,6}$",idExample:"o1a2b3",scriptOrigin:"https://static.ads-twitter.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!0,multiInstance:!0},linkedin:{title:"LinkedIn Insight Tag",vendor:"LinkedIn Ireland Unlimited Company",privacyUrl:"https://www.linkedin.com/legal/privacy-policy",idLabel:"Partner ID",idPattern:"^[0-9]{6,9}$",idExample:"1234567",scriptOrigin:"https://snap.licdn.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!0,multiInstance:!0},tiktok:{title:"TikTok Pixel",vendor:"TikTok Information Technologies UK Limited",privacyUrl:"https://www.tiktok.com/legal/privacy-policy",idLabel:"Pixel ID",idPattern:"^[A-Z0-9]{20}$",idExample:"C4A1B2C3D4E5F6G7H8I9",scriptOrigin:"https://analytics.tiktok.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!1,multiInstance:!0},reddit:{title:"Reddit Pixel",vendor:"Reddit, Inc.",privacyUrl:"https://www.reddit.com/policies/privacy-policy",idLabel:"Advertiser ID",idPattern:"^t2_[a-z0-9]{4,12}$",idExample:"t2_abc123",scriptOrigin:"https://www.redditstatic.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!1,multiInstance:!0},bing_uet:{title:"Microsoft Advertising (UET)",vendor:"Microsoft Corporation",privacyUrl:"https://privacy.microsoft.com/en-us/privacystatement",idLabel:"Tag ID",idPattern:"^[0-9]{7,9}$",idExample:"12345678",scriptOrigin:"https://bat.bing.com",defaultConsentCategory:"marketing",supportsConsentMode:!1,needsConversionIds:!1,multiInstance:!0},clarity:{title:"Microsoft Clarity",vendor:"Microsoft Corporation",privacyUrl:"https://privacy.microsoft.com/en-us/privacystatement",idLabel:"Project ID",idPattern:"^[a-z0-9]{10}$",idExample:"ab12cd34ef",scriptOrigin:"https://www.clarity.ms",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1},hotjar:{title:"Hotjar",vendor:"Hotjar Limited",privacyUrl:"https://www.hotjar.com/legal/policies/privacy/",idLabel:"Site ID",idPattern:"^[0-9]{6,9}$",idExample:"1234567",scriptOrigin:"https://static.hotjar.com",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1},posthog:{title:"PostHog",vendor:"PostHog, Inc.",privacyUrl:"https://posthog.com/privacy",idLabel:"Project API key",idPattern:"^phc_[A-Za-z0-9]{32,48}$",idExample:"phc_abcdefghijklmnopqrstuvwxyz012345",scriptOrigin:"https://us-assets.i.posthog.com",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1,hosts:["us.i.posthog.com","eu.i.posthog.com"]},plausible:{title:"Plausible Analytics",vendor:"Plausible Insights OÜ",privacyUrl:"https://plausible.io/privacy",idLabel:"Domain",idPattern:"^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$",idExample:"example.com",scriptOrigin:"https://plausible.io",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1},ahrefs:{title:"Ahrefs Analytics",vendor:"Ahrefs Pte. Ltd.",privacyUrl:"https://ahrefs.com/privacy",idLabel:"Analytics key",idPattern:"^[A-Za-z0-9+/=]{20,64}$",idExample:"AbCdEfGhIjKlMnOpQrStUv==",scriptOrigin:"https://analytics.ahrefs.com",defaultConsentCategory:"analytics",supportsConsentMode:!1,needsConversionIds:!1}},se=Object.keys(ae);function ce(e){return"string"==typeof e&&Object.prototype.hasOwnProperty.call(ae,e)}function de(e,t){return!!ce(e)&&("string"==typeof t&&0!==t.length&&new RegExp(ae[e].idPattern).test(t))}const le=/^[a-z][a-z0-9-]{0,40}$/,ue=/^[\w.:/@+=-]{1,200}$/;function pe(e){return function(e){if("string"!=typeof e)return!1;if(0===e.length||e.length>300)return!1;let t;try{t=new URL(e)}catch{return!1}return!("https:"!==t.protocol||!t.hostname||!t.hostname.includes(".")||e.includes("?")||e.includes("#")||t.username||t.password)}(e.src)&&function(e){if(null==e)return!0;if("object"!=typeof e||Array.isArray(e))return!1;const t=Object.entries(e);return!(t.length>12)&&t.every(([e,t])=>le.test(e)&&"string"==typeof t&&ue.test(t))}(e.dataAttributes)}const ge=Array.from(new Set(se.map(e=>ae[e].scriptOrigin))).sort(),fe={sign_up:{ga4:"sign_up",meta:"CompleteRegistration",tiktok:"CompleteRegistration",reddit:"SignUp"},login:{ga4:"login",meta:null,tiktok:null,reddit:null},trial_started:{ga4:"begin_checkout",meta:"StartTrial",tiktok:"StartTrial",reddit:"Lead"},checkout_started:{ga4:"begin_checkout",meta:"InitiateCheckout",tiktok:"InitiateCheckout",reddit:"AddToCart"},purchase:{ga4:"purchase",meta:"Purchase",tiktok:"CompletePayment",reddit:"Purchase"},subscription_created:{ga4:"purchase",meta:"Subscribe",tiktok:"Subscribe",reddit:"Purchase"},subscription_upgraded:{ga4:"subscription_upgraded",meta:null,tiktok:null,reddit:null},lead:{ga4:"generate_lead",meta:"Lead",tiktok:"SubmitForm",reddit:"Lead"},workspace_created:{ga4:"workspace_created",meta:null,tiktok:null,reddit:null}},me=Object.keys(fe);function he(e){return me.includes(e)}function ye(){return"undefined"==typeof window?null:window}const we={gtm:"dataLayer",ga4:"gtag",google_ads:"gtag",meta_pixel:"fbq",x_pixel:"twq",linkedin:"lintrk",tiktok:"ttq",reddit:"rdt",bing_uet:"uetq",clarity:"clarity",hotjar:"hj",posthog:"posthog",plausible:"plausible",ahrefs:"__ahrefs_loaded"};function ve(){return"undefined"==typeof window?null:window}function _e(e,t={}){const n=ve();if(!n)return null;const r=n.document.createElement("script");r.async=!0,r.src=e;for(const[e,n]of Object.entries(t))r.setAttribute(e,n);return n.document.head.appendChild(r),r}function be(e){const t=ve();if(!t)return;const n=t.document.createElement("script");n.text=e,t.document.head.appendChild(n)}function ke(e){const t=ve();t&&(Array.isArray(t[e])||(t[e]=[]),"function"!=typeof t.gtag&&(t.gtag=function(){t[e].push(arguments)}))}const Ie=new Set;function Ce(e){for(const t of Ie)if(t.slice(0,t.indexOf(":"))===e)return!0;return!1}function $e(e,t){const n=ve();if(!n)return!1;if("gtm"===e||"ga4"===e||"google_ads"===e){const e=n.google_tag_manager;return!(!e||"object"!=typeof e)&&Object.prototype.hasOwnProperty.call(e,t)}const r=we[e];if(!r)return!1;if(void 0===n[r])return!1;if(Ie.has(`${e}:${t}`))return!0;return!ae[e].multiInstance||!Ce(e)}const Se={meta_pixel:e=>`fbq('init','${e}');fbq('track','PageView');`,x_pixel:e=>`twq('config','${e}');`,tiktok:e=>`ttq.load('${e}');ttq.page();`,reddit:e=>`rdt('init','${e}');rdt('track','PageVisit');`,bing_uet:e=>`window.uetq=window.uetq||[];window.uetq.push({ti:'${e}',enableAutoSpaTracking:false});`,linkedin:e=>`window._linkedin_data_partner_ids=window._linkedin_data_partner_ids||[];window._linkedin_data_partner_ids.push('${e}');`};function Ae(e,t,n){const r=function(e,t,n){const r=ve();if(!r)return!1;if("external"===e.provider){if(!e.src)return!1;const t={};for(const[n,r]of Object.entries(e.dataAttributes??{}))t[`data-${n}`]=r;return _e(e.src,t),!0}const i=e.provider,o=ae[i];if(!o)return!1;const a=e.providerId;if(!a)return!1;const s=Se[i];if(s&&Ce(i))return be(s(a)),!0;switch(i){case"gtm":{ke(t),r[t].push({"gtm.start":Date.now(),event:"gtm.js"});const e="dataLayer"===t?"":`&l=${t}`;return _e(`${o.scriptOrigin}/gtm.js?id=${a}${e}`),!0}case"ga4":case"google_ads":{ke(t),_e(`${o.scriptOrigin}/gtag/js?id=${a}`);const e=r.gtag;e("js",new Date);const s="ga4"===i&&n?.gaClientId?{client_id:n.gaClientId}:void 0;return s?e("config",a,s):e("config",a),!0}case"meta_pixel":return be(`!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,document,'script','${o.scriptOrigin}/en_US/fbevents.js');fbq('init','${a}');fbq('track','PageView');`),!0;case"x_pixel":return be(`!function(e,t,n,s,u,a){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments)},s.version='1.1',s.queue=[],u=t.createElement(n),u.async=!0,u.src='${o.scriptOrigin}/uwt.js',a=t.getElementsByTagName(n)[0],a.parentNode.insertBefore(u,a))}(window,document,'script');twq('config','${a}');`),!0;case"linkedin":return be(`window._linkedin_partner_id='${a}';window._linkedin_data_partner_ids=window._linkedin_data_partner_ids||[];window._linkedin_data_partner_ids.push('${a}');window.lintrk=window.lintrk||function(a,b){(window.lintrk.q=window.lintrk.q||[]).push([a,b])};window.lintrk.q=window.lintrk.q||[];`),_e(`${o.scriptOrigin}/li.lms-analytics/insight.min.js`),!0;case"tiktok":return be(`!function(w,d,t){w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=['page','track','identify','instances','debug','on','off','once','ready','alias','group','enableCookie','disableCookie'];ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.load=function(e,n){var r='${o.scriptOrigin}/i18n/pixel/events.js';ttq._i=ttq._i||{};ttq._i[e]=[];ttq._i[e]._u=r;ttq._t=ttq._t||{};ttq._t[e]=+new Date;ttq._o=ttq._o||{};ttq._o[e]=n||{};var o=d.createElement('script');o.type='text/javascript';o.async=!0;o.src=r+'?sdkid='+e+'&lib='+t;var a=d.getElementsByTagName('script')[0];a.parentNode.insertBefore(o,a)};ttq.load('${a}');ttq.page()}(window,document,'ttq');`),!0;case"reddit":return be(`!function(w,d){if(!w.rdt){var p=w.rdt=function(){p.sendEvent?p.sendEvent.apply(p,arguments):p.callQueue.push(arguments)};p.callQueue=[];var t=d.createElement('script');t.src='${o.scriptOrigin}/ads/pixel.js';t.async=!0;var s=d.getElementsByTagName('script')[0];s.parentNode.insertBefore(t,s)}}(window,document);rdt('init','${a}');rdt('track','PageVisit');`),!0;case"bing_uet":return be(`(function(w,d,t,r,u){w[u]=w[u]||[];w[u].push({ti:'${a}',enableAutoSpaTracking:false});var o=d.createElement(t);o.src='${o.scriptOrigin}/bat.js';o.async=1;var i=d.getElementsByTagName(t)[0];i.parentNode.insertBefore(o,i)})(window,document,'script',0,'uetq');`),!0;case"clarity":return be(`(function(c,l,a,r,i,t,y){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};t=l.createElement(r);t.async=1;t.src='${o.scriptOrigin}/tag/'+i;y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y)})(window,document,'clarity','script','${a}');`),!0;case"hotjar":return be(`(function(h,o,t,j,a,r){h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};h._hjSettings={hjid:${a},hjsv:6};a=o.getElementsByTagName('head')[0];r=o.createElement('script');r.async=1;r.src='${o.scriptOrigin}/hotjar-'+h._hjSettings.hjid+'.js?sv='+h._hjSettings.hjsv;a.appendChild(r)})(window,document);`),!0;case"posthog":{const t=o.hosts,n=t?.includes(e.host??"")?e.host:t?.[0]??"us.i.posthog.com";return be(`!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split('.');2==o.length&&(t=t[o[0]],e=o[1]);t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement('script')).type='text/javascript',p.async=!0,p.src='${o.scriptOrigin}/static/array.js',(r=t.getElementsByTagName('script')[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a='posthog',u.people=u.people||[],u.toString=function(t){var e='posthog';return'posthog'!==a&&(e+='.'+a),t||(e+=' (stub)'),e},u.people.toString=function(){return u.toString(1)+'.people (stub)'},o='init capture register register_once identify alias people.set people.set_once set_config get_distinct_id getFeatureFlag isFeatureEnabled onFeatureFlags reloadFeatureFlags group reset'.split(' '),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);posthog.init('${a}',{api_host:'https://${n}'});`),!0}case"plausible":return be("window.plausible=window.plausible||function(){(window.plausible.q=window.plausible.q||[]).push(arguments)};"),_e(`${o.scriptOrigin}/js/script.js`,{"data-domain":a,defer:"true"}),!0;case"ahrefs":return _e(`${o.scriptOrigin}/analytics.js`,{"data-key":a}),r.__ahrefs_loaded=!0,!0;default:return!1}}(e,t,n);return r&&"external"!==e.provider&&e.providerId&&Ie.add(`${e.provider}:${e.providerId}`),r}const je=Symbol.for("@buildbase/sdk.tracking.context"),xe=globalThis,qe=xe[je]??(xe[je]=s(null)),Ue={consent:{manifest:[],state:null,effective:null,default:null,country:null,set:()=>{}},track:()=>{},setUser:()=>{},setIdentity:()=>{},setConsentRecordHeaders:()=>{},setProperties:()=>{},getProperties:()=>({}),completeCheckout:async()=>{},installed:{},ready:!0,attribution:{}};function Oe(){return a(qe)??Ue}const Pe=({serverUrl:a,orgId:s,clientId:c,enabled:d=!0,consent:u="auto",autoPageview:p=!0,events:g,onEvent:f,properties:m,enrich:h,identity:y,debug:w=!1,children:v})=>{const _=t(y);_.current=y;const[b,I]=n(null),[$,S]=n(!1),[A,j]=n(!1),x="object"==typeof u?JSON.stringify(u):"",q=r(()=>x?function(e){if(!e||"object"!=typeof e)return null;const t=e;if("granted"!==t.default&&"denied"!==t.default)return null;const n=e=>Array.isArray(e)?e.filter(e=>"string"==typeof e):void 0;return{default:t.default,regions:{...n(t.regions?.denied)?{denied:n(t.regions?.denied)}:{},...n(t.regions?.granted)?{granted:n(t.regions?.granted)}:{}}}}(JSON.parse(x)):null,[x]),U="string"==typeof u?u:"auto",O="granted"===U?{analytics:!0,marketing:!0}:"denied"===U?{analytics:!1,marketing:!1}:null,[T,L]=n(O),M=t(null),N=t(f);N.current=f;const R=t(h);R.current=h;const H=t({});H.current=m??{};const G=t({}),Z=i(()=>({...H.current,...G.current}),[]),W=i(e=>{const t={...G.current,...e};for(const[e,n]of Object.entries(t))void 0===n&&delete t[e];G.current=t},[]),[K,Q]=n({}),Y=t({}),[ee,te]=n(0),ne=t(null),[re,se]=n(0),le=t({}),ue=t(null);ue.current=b;const ge=b?.dataLayerName??"dataLayer",me=i((...e)=>{w&&console.info("[buildbase:tracking]",...e)},[w]);o(()=>{return e=()=>{0!==Object.keys(Y.current).length&&window.dispatchEvent("function"==typeof PageTransitionEvent?new PageTransitionEvent("pagehide",{persisted:!1}):new Event("pagehide"))},l.add(e),()=>{l.delete(e)};var e},[]),o(()=>{if(!(d&&a&&s&&c))return void S(!0);let e=!1;const t=`${a.replace(/\/$/,"")}/api/v1/public/${s}/tracking?clientId=${encodeURIComponent(c)}`;return fetch(t).then(e=>e.ok?e.json():null).then(t=>{if(e||!t)return;const n=t.data??t;n&&Array.isArray(n.scripts)&&I(n)}).catch(()=>{me("config fetch failed; nothing installed")}).finally(()=>{e||S(!0)}),()=>{e=!0}},[d,a,s,c,me]),o(()=>{d&&Q(k())},[d]);const we="auto"===U?q??b?.consent?.defaults??null:null,ve=r(()=>b?"auto"!==U?U:q?V(q,b.country,b.region):b.consent?.defaults?b.resolvedConsentDefault??V(b.consent.defaults,b.country,b.region):"denied":null,[b,U,q]),_e=T??("granted"===ve?{analytics:!0,marketing:!0}:null),be=!!b?.enhancedConversions&&!!_e?.marketing,Ie=!!b?.scripts?.some(e=>"ga4"===e.provider||"google_ads"===e.provider||"gtm"===e.provider),Ce=we?JSON.stringify(we):"";o(()=>{d&&b?.enabled&&(ke(ge),function(e,t,n={}){const r=z();if(!r)return;Array.isArray(r[e])||(r[e]=[]),"function"!=typeof r.gtag&&(r.gtag=function(){r[e].push(arguments)});const i=r.gtag,o="auto"===t?n.regional:null;let a="granted"===t?"granted":"denied";if(o){const e=B(o.regions?.denied),t=B(o.regions?.granted).filter(t=>!e.includes(t));e.length&&i("consent","default",{...F("denied"),region:e,wait_for_update:500}),t.length&&i("consent","default",{...F("granted"),region:t}),a=o.default}i("consent","default",{...F(a),..."denied"===a?{wait_for_update:500}:{}}),n.google&&(i("set","url_passthrough",!0),i("set","ads_data_redaction","granted"!==(n.resolved??a)))}(ge,U,{regional:Ce?JSON.parse(Ce):null,resolved:ve,google:Ie}),M.current&&J(M.current))},[d,b?.enabled,ge,U,Ce,Ie]);const Se=r(()=>b?.enabled?b.scripts.filter(e=>{const t=ce(e.provider)&&ae[e.provider].supportsConsentMode;return function(e,t,n,r){return"denied"!==r&&("granted"===r||!!t||!!n&&("marketing"===e?n.marketing:n.analytics))}(e.consentCategory,t,_e,U)}):[],[b,T,ve,U]),[je,xe]=n(()=>"undefined"==typeof window||!C(window.location.search));o(()=>{if(je)return;const e=setInterval(()=>{C(window.location.search)||xe(!0)},50),t=setTimeout(()=>xe(!0),5e3);return()=>{clearInterval(e),clearTimeout(t)}},[je]),o(()=>{if(!je)return;if(!d||!b?.enabled)return void($&&j(!0));let e=0;for(const t of Se)if(!Y.current[t.key]){if("external"===t.provider){if(!pe({src:t.src,dataAttributes:t.dataAttributes})){me("rejected external script",t.key);continue}}else{if(!ce(t.provider)){me("rejected unknown provider",t.provider);continue}if(!de(t.provider,t.providerId)){me("rejected id for",t.provider);continue}if($e(t.provider,t.providerId??"")){me(`${t.provider} ${t.providerId} is already on the page; skipping. Configure each tag in exactly one place.`);continue}}Ae(t,ge,_.current)&&(Y.current[t.key]=t.providerId??t.src??"",e+=1,me("installed",t.key))}e&&te(e=>e+1);const t=window;t.__buildbase=t.__buildbase??{},t.__buildbase.tracking={installed:{...Y.current},dataLayerName:ge,clientId:c};const n=Object.keys(Y.current).length>0,r=null!==_e||0===b.scripts.length;(n||r)&&j(!0)},[d,b,Se,$,T,ve,ge,me,je,c]),o(()=>{if(!d||!p||!b?.enabled)return;if("undefined"==typeof window)return;if(!je)return;let e=null;const t=()=>{e&&clearTimeout(e),e=setTimeout(()=>function(e,t){const n=ye();if(!n)return;const r=n[t];Array.isArray(r)&&r.push({event:"page_view",page_path:n.location.pathname,page_location:n.location.href,page_title:n.document.title});for(const t of e)switch(t.provider){case"ga4":n.gtag?.("event","page_view",{send_to:t.providerId,page_path:n.location.pathname,page_location:n.location.href,page_title:n.document.title});break;case"meta_pixel":n.fbq?.("track","PageView");break;case"tiktok":{const e=n.ttq;e?.page?.();break}case"reddit":n.rdt?.("track","PageVisit")}}(Se,ge),50)},n=window.history,r=n.pushState,i=n.replaceState;return n.pushState=function(...e){const n=r.apply(this,e);return t(),n},n.replaceState=function(...e){const n=i.apply(this,e);return t(),n},window.addEventListener("popstate",t),()=>{n.pushState=r,n.replaceState=i,window.removeEventListener("popstate",t),e&&clearTimeout(e)}},[d,p,b?.enabled,Se,ge,je]),o(()=>{if(!d)return;const e=function(e,t){const n=e?.mode??"auto",r=e?.overrides??{};if(("manual"===n||Object.values(r).some(e=>"manual"===e))&&!t)return'[buildbase:tracking] events are set to "manual" but no onEvent handler was provided, so those events would never fire anywhere. Pass onEvent, or use mode "auto".';for(const e of Object.keys(r))if(!he(e))return`[buildbase:tracking] unknown event "${e}" in events.overrides. Overrides only apply to the events the SDK fires itself.`;return null}(g,!!f);if(e)throw new Error(e)},[d,g,f]);const Ue=i((e,t={},n)=>{if(!d)return;const r=n?.eventId||function(){const e=globalThis.crypto;return e?.randomUUID?e.randomUUID():`${Date.now().toString(16)}-${Math.random().toString(16).slice(2,10)}`}(),i=g?.mode??"auto",o=(he(e)?g?.overrides?.[e]:void 0)??i,a={...H.current,...G.current,...K,...t},s=R.current?.({name:e,params:a})??{},c={...a,...s},l=N.current?.({name:e,params:c,eventId:r,handledBy:o});"manual"!==o&&!0!==l?(be&&ne.current&&oe(Se,ne.current),function(e,t,n,r,i){const o=ye();if(!o)return;const a=o[i];Array.isArray(a)&&a.push({event:e,...t,event_id:n});const s=he(e)?fe[e]:{ga4:e,meta:null,tiktok:null,reddit:null};for(const i of r){const r=i.provider,a=ae[r];if(a){if(a.needsConversionIds){const a=i.conversionIds?.[e];if(!a)continue;"google_ads"===r?o.gtag?.("event","conversion",{send_to:`${i.providerId}/${a}`,transaction_id:n,...t}):"x_pixel"===r?o.twq?.("event",a,{...t,conversion_id:n}):"linkedin"===r&&o.lintrk?.("track",{conversion_id:a});continue}switch(r){case"ga4":s.ga4&&o.gtag?.("event",s.ga4,{...t,send_to:i.providerId,event_id:n});break;case"meta_pixel":s.meta&&o.fbq?.("track",s.meta,t,{eventID:n});break;case"tiktok":if(s.tiktok){const e=o.ttq;e?.track?.(s.tiktok,{...t,event_id:n})}break;case"reddit":s.reddit&&o.rdt?.("track",s.reddit,{...t,conversionId:n});break;case"bing_uet":{const r=o.uetq;r?.push?.("event",s.ga4??e,{...t,event_id:n});break}case"clarity":o.clarity?.("event",e);break;case"hotjar":{const t=o.hj;t?.("event",e);break}case"posthog":{const r=o.posthog;r?.capture?.(e,{...t,event_id:n});break}case"plausible":o.plausible?.(e,{props:t})}}}}(e,c,r,Se,ge),me("event fired:",e,r)):me("event handled by app:",e)},[d,g,Se,ge,K,me,be]),Oe=i(async(e,t={})=>{const n=function(e){return{name:"trial_started"===e.kind?"trial_started":"purchase",params:{...e.workspaceId?{workspace_id:e.workspaceId}:{},...e.planVersionId?{plan_version_id:e.planVersionId}:{},...e.creditPackageId?{credit_package_id:e.creditPackageId}:{},...e.billingInterval?{billing_interval:e.billingInterval}:{},...e.currency?{currency:e.currency.toUpperCase()}:{},..."number"==typeof e.value?{value:e.value}:{},...e.sessionId?{transaction_id:e.sessionId}:{}}}}(e);let r=n.params;if(e.sessionId&&a&&s){const t=await async function(e,t){try{const n=e.serverUrl.replace(/\/$/,""),r=await fetch(`${n}/api/v1/public/${encodeURIComponent(e.orgId)}/checkout/${encodeURIComponent(t)}`,{credentials:"omit",..."undefined"!=typeof AbortSignal&&AbortSignal.timeout?{signal:AbortSignal.timeout(2e3)}:{}});if(!r.ok)return null;const i=await r.json(),o=i?.data??i;return"number"!=typeof o?.amount?null:{value:D(o.amount,o.currency),currency:"string"==typeof o.currency?o.currency:void 0,...Array.isArray(o.items)&&o.items.length?{items:o.items}:{}}}catch{return null}}({serverUrl:a,orgId:s},e.sessionId);t&&"number"==typeof t.value&&(r={...r,value:t.value,...t.currency?{currency:t.currency.toUpperCase()}:{},...t.items?.length?{items:t.items}:{}})}if(Ue(n.name,{...r,...t},{eventId:e.eventId}),"purchase"===n.name&&e.sessionId&&a&&s){const t=(b?.scripts??[]).find(e=>"ga4"===e.provider&&e.providerId);t&&$e("ga4",t.providerId??"")&&function(e,t,n){try{const r=e.serverUrl.replace(/\/$/,"");fetch(`${r}/api/v1/public/${encodeURIComponent(e.orgId)}/checkout/${encodeURIComponent(t)}/reported`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:n}),keepalive:!0,credentials:"omit"}).catch(()=>{})}catch{}}({serverUrl:a,orgId:s},e.sessionId,"ga4")}},[a,s,Ue,b]),[Pe]=n(()=>"undefined"==typeof window?"":window.location.search);o(()=>{if(!d||!A)return;if("undefined"==typeof window)return;const e=P(window.location.search);if(e)return void Oe(e);const t=E(Pe);t&&Ue("checkout_abandoned",{...t.workspaceId?{workspace_id:t.workspaceId}:{},...t.planVersionId?{plan_version_id:t.planVersionId}:{},...t.creditPackageId?{credit_package_id:t.creditPackageId}:{},...t.billingInterval?{billing_interval:t.billingInterval}:{},...t.currency?{currency:t.currency.toUpperCase()}:{},..."number"==typeof t.value?{value:t.value}:{},seconds_at_checkout:Math.max(0,Math.round((Date.now()-t.startedAt)/1e3))})},[d,A,Oe,Pe,Ue]);const Ee=i((e,t)=>{M.current=e,L(e),J(e),d&&X({serverUrl:a,orgId:s,clientId:c,state:e,manifestVersion:ue.current?.consent?.manifestVersion,source:t?.source,consentString:t?.consentString,headers:le.current})},[d,a,s,c]),Te=i(e=>{le.current={...e}},[]),Le=i(e=>{if(!e)return ne.current=null,void se(e=>e+1);ie(e).then(e=>{ne.current=e.emailHash||e.phoneHash?e:null,se(e=>e+1)})},[]),De=i((e,t)=>{const n=function(e){if(!e)return{traits:e,identity:null};const{email:t,phone:n,...r}=e,i={};return"string"==typeof t&&t&&(i.email=t),"string"==typeof n&&n&&(i.phone=n),{traits:r,identity:i.email||i.phone?i:null}}(t);n.identity&&Le(n.identity),function(e,t,n){const r=ye();if(!r)return;const i=!!n&&Object.keys(n).length>0;for(const o of t)switch(o.provider){case"ga4":case"google_ads":r.gtag?.("set",{user_id:e}),i&&r.gtag?.("set",{user_properties:n});break;case"meta_pixel":o.providerId&&r.fbq?.("init",o.providerId,{external_id:e});break;case"posthog":r.posthog?.identify?.(e,i?n:void 0);break;case"clarity":if(r.clarity?.("identify",e),i)for(const[e,t]of Object.entries(n))r.clarity?.("set",e,String(t));break;case"hotjar":r.hj?.("identify",e,{});break;case"tiktok":{const t=r.ttq;t?.identify?.({external_id:e});break}}}(e,Se,n.traits)},[Se,Le]);o(()=>{be&&ne.current&&0!==Object.keys(Y.current).length&&oe(Se,ne.current)},[be,Se,re,ee]);const Me=r(()=>({consent:{manifest:b?.consent?.manifest??[],state:T,effective:_e,default:ve,country:b?.country??null,set:Ee},track:Ue,setUser:De,setIdentity:Le,setConsentRecordHeaders:Te,setProperties:W,getProperties:Z,completeCheckout:Oe,installed:{...Y.current},ready:A,attribution:K}),[b,T,ve,Ee,Ue,De,Le,Te,W,Z,Oe,A,ee,K]);return e(qe.Provider,{value:Me,children:v})};function Ee(e={}){const{completeCheckout:n,ready:r}=Oe(),i=t(e);i.current=e;const a=t(!1);o(()=>{if(!r)return;if(a.current)return;const e=P(window.location.search)??U();e&&(a.current=!0,n(e,i.current))},[r,n])}Pe.displayName="BuildBaseTracking";const Te={sign_in_started:"The sign-in / sign-up button was pressed.",pricing_viewed:"A <PricingPage> finished loading its plans.",pricing_plan_selected:"A plan was chosen on a <PricingPage>.",workspace_switcher_opened:"The workspace switcher was opened.",workspace_settings_opened:"The workspace settings modal was opened.",workspace_settings_section_viewed:"A different section of the settings modal was opened.",plan_picker_opened:"The plan picker was shown.",billing_interval_changed:"Monthly / quarterly / yearly was switched in the plan picker.",plan_selected:"A plan was chosen in the plan picker.",plan_picker_dismissed:"The plan picker was closed without choosing a plan.",checkout_abandoned:"The customer came back from Stripe without paying.",billing_portal_opened:"Stripe’s billing portal was opened.",subscription_cancel_started:"The cancel-subscription confirmation was opened.",subscription_cancelled:"A subscription was cancelled.",subscription_resumed:"A cancelled subscription was resumed.",feature_gate_shown:'A feature gate rendered its "not on your plan" side.',quota_limit_reached:"A quota gate rendered because a quota is used up.",quota_threshold_reached:"A usage-threshold gate rendered.",plan_gate_shown:'A plan gate rendered its "needs another plan" side.',subscription_notice_shown:"A billing notice (trial ending, payment failed…) was shown.",sdk_error:"An SDK operation failed (component, action and code only)."};export{p as ATTRIBUTION_PARAMS,Pe as BuildBaseTracking,M as EEA_COUNTRIES,fe as EVENT_MAPPINGS,Te as FUNNEL_EVENTS,N as SAFE_REGIONAL_CONSENT,ae as TAG_PROVIDERS,se as TAG_PROVIDER_IDS,ge as TAG_SCRIPT_ORIGINS,k as captureAttribution,B as expandRegions,I as getAttribution,ie as hashIdentity,he as isCanonicalEvent,ce as isTagProviderId,de as isValidProviderId,te as normalizeEmail,ne as normalizePhone,V as resolveConsentDefault,Ee as useCheckoutCompleted,Oe as useTracking};
@@ -0,0 +1,297 @@
1
+ # Content from your server
2
+
3
+ Blogs, docs, FAQs, testimonials, rich content and collection data are read
4
+ with an **org API token**. That token is your organization's key, so these
5
+ reads happen on your server or at build time, never in a browser.
6
+
7
+ `@buildbase/sdk/server` does the reading, caches it, and keeps the cache
8
+ honest when content changes. It works on any JavaScript server runtime, and
9
+ the HTTP rules underneath work from any language.
10
+
11
+ - [Pick a pattern](#pick-a-pattern)
12
+ - [Server client](#server-client)
13
+ - [Caching](#caching)
14
+ - [Content webhooks](#content-webhooks)
15
+ - [Build-time pull](#build-time-pull)
16
+ - [Next.js](#nextjs)
17
+ - [Other languages](#other-languages)
18
+ - [Reference](#reference)
19
+
20
+ ## Pick a pattern
21
+
22
+ | Your app | Use |
23
+ | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
24
+ | Has a server (Express, Fastify, NestJS, Hono, Remix, Astro SSR, Next) | [Server client](#server-client) with the [webhook](#content-webhooks) |
25
+ | Static site, single-page app, or no backend | [Build-time pull](#build-time-pull), rebuilt by a deploy hook when content changes |
26
+ | Not JavaScript (Python, Go, PHP, Ruby, Java) | [The HTTP API directly](#other-languages), with `If-None-Match` and the same webhook |
27
+
28
+ Whichever you pick, a page render should not call BuildBase. Fetch once, cache,
29
+ and let a webhook tell you when to fetch again. Reads that ignore caching
30
+ count against your plan's content-read allowance.
31
+
32
+ ## Server client
33
+
34
+ ```ts
35
+ import { createServerClient } from '@buildbase/sdk/server';
36
+
37
+ export const content = createServerClient({
38
+ serverUrl: 'https://api.console.buildbase.app',
39
+ apiToken: process.env.BUILDBASE_API_TOKEN!, // <orgId>:<secret>
40
+ });
41
+
42
+ const posts = await content.blogs.list({ limit: 20, sort: { publishedAt: -1 } });
43
+ const post = await content.blogs.byPath('guides/getting-started');
44
+ const refund = await content.richContent.get('refund-policy');
45
+ const questions = await content.faqs.questions('help-center');
46
+ const quotes = await content.testimonials.list();
47
+ const releases = await content.collections.data<{ title: string; version: string }>(
48
+ 'release-notes'
49
+ );
50
+ ```
51
+
52
+ Create the token in the console under **Settings, API tokens**. Give it the
53
+ read-only **content-reader** role: a token that can render a blog should not
54
+ be able to change your billing.
55
+
56
+ The client refuses to run in a browser. Bundlers building for the browser
57
+ resolve `@buildbase/sdk/server` to a module that throws at load, so a stray
58
+ import fails the build loudly instead of shipping your token.
59
+
60
+ Runtimes: Node 18+, Bun, Deno, Cloudflare Workers, Vercel and Netlify edge.
61
+ It uses only the standard `fetch`, `Request` and `Response`.
62
+
63
+ ### Express, Fastify, NestJS
64
+
65
+ ```ts
66
+ import express from 'express';
67
+ import { createContentWebhookHandler, toNodeHandler } from '@buildbase/sdk/server';
68
+ import { content } from './content';
69
+
70
+ const app = express();
71
+
72
+ app.get('/blog/:slug', async (req, res) => {
73
+ const post = await content.blogs.byPath(req.params.slug);
74
+ if (!post) return res.status(404).send('Not found');
75
+ res.render('post', { post });
76
+ });
77
+
78
+ // A raw body: the signature covers the exact bytes BuildBase sent.
79
+ app.post(
80
+ '/webhooks/buildbase',
81
+ express.raw({ type: 'application/json' }),
82
+ toNodeHandler(
83
+ createContentWebhookHandler({
84
+ secret: process.env.BUILDBASE_WEBHOOK_SECRET!,
85
+ cache: content.cache,
86
+ })
87
+ )
88
+ );
89
+ ```
90
+
91
+ Fastify and NestJS take the same `toNodeHandler(...)`; give the route a raw
92
+ body (a content-type parser that keeps the payload as a string or Buffer).
93
+
94
+ ### Hono, Cloudflare Workers, Deno, Bun
95
+
96
+ ```ts
97
+ import { Hono } from 'hono';
98
+ import { createServerClient, handleContentWebhook, kvCache } from '@buildbase/sdk/server';
99
+
100
+ type Env = { BUILDBASE_API_TOKEN: string; BUILDBASE_WEBHOOK_SECRET: string; CONTENT: KVNamespace };
101
+
102
+ const app = new Hono<{ Bindings: Env }>();
103
+ const client = (env: Env) =>
104
+ createServerClient({
105
+ serverUrl: 'https://api.console.buildbase.app',
106
+ apiToken: env.BUILDBASE_API_TOKEN,
107
+ cache: kvCache(env.CONTENT), // shared across isolates
108
+ });
109
+
110
+ app.get('/faq', async c => c.json(await client(c.env).faqs.questions('help-center')));
111
+
112
+ app.post('/webhooks/buildbase', c =>
113
+ handleContentWebhook(c.req.raw, {
114
+ secret: c.env.BUILDBASE_WEBHOOK_SECRET,
115
+ cache: client(c.env).cache,
116
+ })
117
+ );
118
+
119
+ export default app;
120
+ ```
121
+
122
+ ## Caching
123
+
124
+ Every read is cached. While an entry is fresh, a read costs nothing. Once it
125
+ is stale, the client asks BuildBase with `If-None-Match`; if nothing changed
126
+ the answer is an empty `304`, served from BuildBase's own cache without
127
+ touching its database.
128
+
129
+ | Option | Default | Meaning |
130
+ | ------------------- | --------------- | ----------------------------------------------------------------------------------------- |
131
+ | `cache` | `memoryCache()` | Where entries live. `false` turns caching off. |
132
+ | `defaultTtlSeconds` | `60` | Freshness when the response carries no `Cache-Control: max-age`. |
133
+ | `retainSeconds` | `86400` | How long a stale entry is kept, for revalidation and the error fallback. |
134
+ | `staleOnError` | `true` | Serve the last good copy if BuildBase errors or is unreachable. 401 and 403 always throw. |
135
+ | `timeoutMs` | `10000` | Per request. |
136
+
137
+ Stores:
138
+
139
+ - `memoryCache({ maxEntries })`: per process. Fine for one server.
140
+ - `redisCache(client, { prefix })`: shared. ioredis and node-redis v4+ both work.
141
+ - `kvCache(binding, { prefix })`: Cloudflare Workers KV, or Upstash Redis REST.
142
+ - Your own: implement `CacheStore` (`get`, `set`, `delete`, `deleteByTag`).
143
+
144
+ Identical reads that arrive at the same time share one request.
145
+
146
+ BuildBase answers content reads with
147
+ `Cache-Control: private, max-age=60, stale-while-revalidate=300`. The client
148
+ honours both numbers: an entry is fresh for 60 seconds, and for the five
149
+ minutes after that a read gets the cached copy at once while one background
150
+ request revalidates it. Only past both does a read wait for BuildBase.
151
+ `private` does not stop the client caching; it tells shared proxies and CDNs
152
+ not to store a response that was fetched with your token, and this cache lives
153
+ on your own server.
154
+
155
+ ### Tags
156
+
157
+ Each cached read carries tags, and `content.revalidate(tag)` drops everything
158
+ under one. The same strings appear in content webhooks:
159
+
160
+ | Tag | Covers |
161
+ | ----------------------------- | ----------------------------------------- |
162
+ | `buildbase:blog` | every blog list |
163
+ | `buildbase:blog:<slug>` | one post, by slug (same for every module) |
164
+ | `buildbase:blog:id:<id>` | one post, by id |
165
+ | `buildbase:collection:<slug>` | every record of one collection |
166
+ | `buildbase:all` | everything this client cached |
167
+
168
+ Modules: `blog`, `doc`, `faq`, `faq_collection`, `testimonial`,
169
+ `rich_content`, `collection`. `contentTags.*` builds them, and
170
+ `getContentTags(result)` tells you which tags a result was stored under.
171
+
172
+ ## Content webhooks
173
+
174
+ In the console, under **Settings, Webhooks**, add an endpoint pointing at your
175
+ route and subscribe it to the content events (or to everything; the handler
176
+ ignores what it does not need):
177
+
178
+ `blog.published`, `blog.updated`, `blog.unpublished`, `blog.deleted`, the same
179
+ four for `doc`, `faq.updated`, `faq_collection.updated`,
180
+ `testimonial.updated`, `testimonial.deleted`, `rich_content.updated`,
181
+ `rich_content.deleted`, `collection.version_published`,
182
+ `collection.record_created`, `collection.record_updated`,
183
+ `collection.record_deleted`.
184
+
185
+ `handleContentWebhook(request, { secret, cache })` verifies the signature
186
+ (HMAC-SHA256 over `<timestamp>.<body>`, five-minute window), drops the tags the
187
+ event names, and answers `200`. A bad signature gets `401`. Pass `revalidate`
188
+ instead of, or as well as, `cache` to invalidate a framework's own cache, and
189
+ `onEvent` to trigger anything else, such as a static site rebuild.
190
+
191
+ ## Build-time pull
192
+
193
+ For sites with no server of their own: pull the content once, in CI, and ship
194
+ it as a JSON file. The token stays in CI.
195
+
196
+ ```bash
197
+ BUILDBASE_SERVER_URL=https://api.console.buildbase.app \
198
+ BUILDBASE_API_TOKEN=$BUILDBASE_API_TOKEN \
199
+ npx buildbase content pull --out src/content/buildbase.json
200
+ ```
201
+
202
+ | Flag | Default |
203
+ | ----------------------- | ------------------------------------------------------ |
204
+ | `--out <file>` | required |
205
+ | `--modules <list>` | `blogs,docs,faqs,testimonials,richContent,collections` |
206
+ | `--collections <slugs>` | every live collection |
207
+ | `--page-size <n>` | `100` |
208
+ | `--server-url <url>` | `BUILDBASE_SERVER_URL` |
209
+
210
+ The file is `{ generatedAt, blogs, docs, faqs, testimonials, richContent, collections }`,
211
+ with published content only. `pullContent(client, options)` does the same from
212
+ your own build script.
213
+
214
+ To rebuild when content changes, point a content webhook at a small function
215
+ that calls your host's deploy hook, or use the console's deploy hooks
216
+ (**Settings, Deployments**).
217
+
218
+ ## Next.js
219
+
220
+ Next.js has its own data cache, keyed by tags. `@buildbase/sdk/server/next`
221
+ hands caching to it:
222
+
223
+ ```ts
224
+ // lib/content.ts
225
+ import { createServerClient } from '@buildbase/sdk/server';
226
+ import { withNextCache } from '@buildbase/sdk/server/next';
227
+
228
+ export const content = createServerClient({
229
+ serverUrl: process.env.BUILDBASE_SERVER_URL!,
230
+ apiToken: process.env.BUILDBASE_API_TOKEN!,
231
+ ...withNextCache({ revalidate: 300 }),
232
+ });
233
+ ```
234
+
235
+ ```ts
236
+ // app/api/webhooks/buildbase/route.ts
237
+ import { createNextWebhookHandler } from '@buildbase/sdk/server/next';
238
+
239
+ export const POST = createNextWebhookHandler({ secret: process.env.BUILDBASE_WEBHOOK_SECRET! });
240
+ ```
241
+
242
+ Every read goes out with `{ next: { tags, revalidate } }`, and the webhook calls
243
+ `revalidateTag` for what changed. `next` is an optional peer dependency; apps
244
+ on other frameworks never load it.
245
+
246
+ ## Other languages
247
+
248
+ The client is a convenience; the rules are HTTP.
249
+
250
+ - Send the token as `Authorization: Bearer <orgId>:<secret>` from your server.
251
+ - Reads answer with `ETag` and `Cache-Control`. Store the body and the ETag;
252
+ send `If-None-Match: <etag>` next time and a `304` means your copy is current.
253
+ - `filter` and `sort` are bracket-encoded: `?filter[published]=true&sort[publishedAt]=-1&$limit=20`.
254
+ - Verify webhooks: `hex(HMAC-SHA256(secret, timestamp + "." + rawBody))` must
255
+ equal the part after `sha256=` in `x-buildbase-signature`, and
256
+ `x-buildbase-timestamp` must be within five minutes. Then drop `data.tags`.
257
+
258
+ ```bash
259
+ curl -s -D - -H "Authorization: Bearer $BUILDBASE_API_TOKEN" \
260
+ "https://api.console.buildbase.app/api/rich-content/slug/refund-policy"
261
+ ```
262
+
263
+ ```python
264
+ import hmac, hashlib, time
265
+
266
+ def verify(secret: str, body: bytes, signature: str, timestamp: str) -> bool:
267
+ if abs(time.time() - int(timestamp)) > 300:
268
+ return False
269
+ expected = hmac.new(secret.encode(), timestamp.encode() + b"." + body, hashlib.sha256).hexdigest()
270
+ return hmac.compare_digest("sha256=" + expected, signature)
271
+ ```
272
+
273
+ ## Reference
274
+
275
+ | Call | Endpoint | Returns |
276
+ | ---------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------ |
277
+ | `blogs.list({ page, limit, filter, sort, includeDrafts })` | `GET /api/blogs` | `Paginated<BlogPost>`, published only by default |
278
+ | `blogs.get(id)` | `GET /api/blogs/:id` | `BlogPost \| null` |
279
+ | `blogs.byPath(path, { draftPreview })` | `GET /api/blogs/path?path=` | `BlogPost \| null` |
280
+ | `blogs.tree({ folder })` | `GET /api/blogs/folders/tree` | folder tree |
281
+ | `blogs.tags()`, `blogs.authors()` | `GET /api/blogs/tags`, `/authors` | `Paginated<...>` |
282
+ | `docs.*` | the same under `/api/docs` | `DocPage` |
283
+ | `faqs.collections()` | `GET /api/faqs/collections` | `Paginated<FaqCollection>` |
284
+ | `faqs.collection(slugOrId)` | `GET /api/faqs/collections/slug/:slug` or `/:id` | `FaqCollection \| null` |
285
+ | `faqs.questions(slugOrId)` | `GET /api/faqs/collections/slug/:slug/faqs` or `/:id/faqs` | `Faq[]`, `[]` when the collection does not exist |
286
+ | `testimonials.list({ includeUnpublished })` | `GET /api/testimonials` | published only by default |
287
+ | `testimonials.get(id)` | `GET /api/testimonials/:id` | `Testimonial \| null` |
288
+ | `richContent.get(slug)`, `.list()` | `GET /api/rich-content/slug/:slug` | `RichContent \| null` |
289
+ | `collections.data(slug, { version })`, `.list()` | `GET /api/collections/data/:slug?latest=true`, or `?version=` | `CollectionRecord[]` |
290
+ | `revalidate(tag)`, `revalidateAll()` | | drops cached reads |
291
+
292
+ The slug routes for FAQ collections, `GET /api/testimonials/:id` and
293
+ collection data without a `version` need the BuildBase server release that
294
+ ships content delivery; an older server answers those with 404 or 400. The
295
+ rest of the table works on any server.
296
+
297
+ Errors are `BuildBaseContentError` with `status`, `url` and the response `body`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildbase/sdk",
3
- "version": "0.0.71",
3
+ "version": "0.0.74",
4
4
  "type": "module",
5
5
  "description": "A SDK for Buildbase",
6
6
  "main": "dist/index.cjs",
@@ -37,12 +37,57 @@
37
37
  "require": "./dist/mcp/index.cjs",
38
38
  "default": "./dist/mcp/index.cjs"
39
39
  },
40
+ "./server": {
41
+ "types": "./dist/server/index.d.ts",
42
+ "workerd": "./dist/server/index.mjs",
43
+ "worker": "./dist/server/index.mjs",
44
+ "edge-light": "./dist/server/index.mjs",
45
+ "deno": "./dist/server/index.mjs",
46
+ "bun": "./dist/server/index.mjs",
47
+ "react-server": {
48
+ "import": "./dist/server/index.mjs",
49
+ "require": "./dist/server/index.cjs"
50
+ },
51
+ "node": {
52
+ "import": "./dist/server/index.mjs",
53
+ "require": "./dist/server/index.cjs"
54
+ },
55
+ "browser": {
56
+ "import": "./dist/server/browser.mjs",
57
+ "require": "./dist/server/browser.cjs"
58
+ },
59
+ "import": "./dist/server/index.mjs",
60
+ "require": "./dist/server/index.cjs",
61
+ "default": "./dist/server/index.cjs"
62
+ },
63
+ "./server/next": {
64
+ "types": "./dist/server/next/index.d.ts",
65
+ "edge-light": "./dist/server/next/index.mjs",
66
+ "react-server": {
67
+ "import": "./dist/server/next/index.mjs",
68
+ "require": "./dist/server/next/index.cjs"
69
+ },
70
+ "node": {
71
+ "import": "./dist/server/next/index.mjs",
72
+ "require": "./dist/server/next/index.cjs"
73
+ },
74
+ "browser": {
75
+ "import": "./dist/server/browser.mjs",
76
+ "require": "./dist/server/browser.cjs"
77
+ },
78
+ "import": "./dist/server/next/index.mjs",
79
+ "require": "./dist/server/next/index.cjs",
80
+ "default": "./dist/server/next/index.cjs"
81
+ },
40
82
  "./css": {
41
83
  "types": "./dist/css/styles.d.ts",
42
84
  "default": "./dist/css/styles.css"
43
85
  },
44
86
  "./package.json": "./package.json"
45
87
  },
88
+ "bin": {
89
+ "buildbase": "dist/cli.mjs"
90
+ },
46
91
  "typesVersions": {
47
92
  "*": {
48
93
  "react": [
@@ -59,6 +104,12 @@
59
104
  ],
60
105
  "tracking": [
61
106
  "./dist/tracking/index.d.ts"
107
+ ],
108
+ "server": [
109
+ "./dist/server/index.d.ts"
110
+ ],
111
+ "server/next": [
112
+ "./dist/server/next/index.d.ts"
62
113
  ]
63
114
  }
64
115
  },
@@ -71,14 +122,17 @@
71
122
  "docs/ERROR_CODES.md",
72
123
  "docs/MCP-AND-AGENT-READINESS.md",
73
124
  "docs/THEMING.md",
74
- "docs/UI-CONFIG.md"
125
+ "docs/UI-CONFIG.md",
126
+ "docs/SERVER-CONTENT.md"
75
127
  ],
76
128
  "sideEffects": [
77
- "**/*.css"
129
+ "**/*.css",
130
+ "./dist/server/browser.mjs",
131
+ "./dist/server/browser.cjs"
78
132
  ],
79
133
  "scripts": {
80
134
  "build": "rollup -c && rollup -c rollup.dts.config.js && npm run postbuild",
81
- "postbuild": "rimraf dist/types dist/react/types dist/data/types dist/mcp/types dist/tracking/types dist/*.map dist/react/*.map dist/data/*.map dist/mcp/*.map dist/tracking/*.map && mkdir -p dist/css && [ -f dist/react/styles.css ] && mv dist/react/styles.css dist/css/styles.css || true && cp src/css.d.ts dist/css/styles.d.ts",
135
+ "postbuild": "rimraf dist/types dist/react/types dist/data/types dist/mcp/types dist/tracking/types dist/server/types dist/server/next/types dist/server/browser-types dist/cli-types dist/*.map dist/react/*.map dist/data/*.map dist/mcp/*.map dist/tracking/*.map dist/server/*.map dist/server/next/*.map && mkdir -p dist/css && [ -f dist/react/styles.css ] && mv dist/react/styles.css dist/css/styles.css || true && cp src/css.d.ts dist/css/styles.d.ts",
82
136
  "build:analyze": "rollup --config rollup.config.analyze.js",
83
137
  "dev": "rollup -c -w",
84
138
  "clean": "rimraf dist",
@@ -103,7 +157,13 @@
103
157
  },
104
158
  "peerDependencies": {
105
159
  "react": "^18.0.0 || ^19.0.0",
106
- "react-dom": "^18.0.0 || ^19.0.0"
160
+ "react-dom": "^18.0.0 || ^19.0.0",
161
+ "next": ">=13"
162
+ },
163
+ "peerDependenciesMeta": {
164
+ "next": {
165
+ "optional": true
166
+ }
107
167
  },
108
168
  "dependencies": {
109
169
  "@hookform/resolvers": "^5.0.1",