UNPKG

@cliqdigital/bloomreach-sdk

Version:

React component library for integrating Bloomreach SDK with push notifications support

250 lines (249 loc) 16.7 kB
"use strict"; 'use client'; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.NextBloomreachProvider = void 0; var react_1 = __importDefault(require("react")); var BloomreachContext_1 = require("../context/BloomreachContext"); var NotificationHandler_1 = require("./NotificationHandler"); var NextBloomreachProvider = /** @class */ (function (_super) { __extends(NextBloomreachProvider, _super); function NextBloomreachProvider(props) { var _this = _super.call(this, props) || this; _this.requestNotificationPermission = function () { return __awaiter(_this, void 0, void 0, function () { var result, e_1; var _a, _b, _c, _d; return __generator(this, function (_e) { switch (_e.label) { case 0: _e.trys.push([0, 3, , 4]); if (!this.state.browserSupported) { console.log('Browser does not support notifications, skipping permission request'); return [2 /*return*/]; } if (!(typeof Notification !== 'undefined')) return [3 /*break*/, 2]; return [4 /*yield*/, Notification.requestPermission()]; case 1: result = _e.sent(); if (result === 'granted') { console.log('Notification permission granted'); this.setState({ hasConsent: true }); // Track the consent event with the correct format window.exponea.track("consent", { category: "browser_notifications", action: "accept", timestamp: new Date().toISOString(), valid_until: "unlimited", source: "public_api", identification_type: "cookie" }); // Track the specific push notification event window.exponea.track('push_notification_consent', { status: 'granted', timestamp: new Date().toISOString() }); (_b = (_a = this.props.config).onConsentGranted) === null || _b === void 0 ? void 0 : _b.call(_a); } else { this.setState({ hasConsent: false }); // Track the consent event with the correct format window.exponea.track("consent", { category: "browser_notifications", action: "reject", timestamp: new Date().toISOString(), source: "public_api", identification_type: "cookie" }); (_d = (_c = this.props.config).onConsentDenied) === null || _d === void 0 ? void 0 : _d.call(_c); } _e.label = 2; case 2: return [3 /*break*/, 4]; case 3: e_1 = _e.sent(); console.error('Error requesting notification permission:', e_1); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; _this.state = { isInitialized: false, error: null, isClient: false, hasConsent: false, browserSupported: true }; return _this; } NextBloomreachProvider.prototype.componentDidMount = function () { var _this = this; this.setState({ isClient: true, browserSupported: this.checkBrowserSupport() }, function () { _this.initializeSDK(); }); }; // Check if the browser supports push notifications NextBloomreachProvider.prototype.checkBrowserSupport = function () { if (typeof window === 'undefined') return false; // iOS Safari detection var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); // Push notifications are not supported on iOS Safari if (isIOS && isSafari) { console.log('iOS Safari detected - push notifications not supported'); return false; } // Check if notifications API is available if (!('Notification' in window)) { console.log('Notifications API not supported in this browser'); return false; } // Check if service workers are supported if (!('serviceWorker' in navigator)) { console.log('Service Workers not supported in this browser'); return false; } return true; }; NextBloomreachProvider.prototype.initializeSDK = function () { return __awaiter(this, void 0, void 0, function () { var config_1, script; var _this = this; return __generator(this, function (_a) { try { config_1 = this.props.config; if (!config_1.projectToken) { throw new Error('Bloomreach project token is missing'); } if (typeof window !== 'undefined') { script = document.createElement('script'); script.type = 'text/javascript'; script.innerHTML = "\n !function(e,n,t,i,r,o){function s(e){if(\"number\"!=typeof e)return e;var n=new Date;return new Date(n.getTime()+1e3*e)}var a=4e3,c=\"xnpe_async_hide\";function p(e){return e.reduce((function(e,n){return e[n]=function(){e._.push([n.toString(),arguments])},e}),{_:[]})}function m(e,n,t){var i=t.createElement(n);i.src=e;var r=t.getElementsByTagName(n)[0];return r.parentNode.insertBefore(i,r),i}function u(e){return\"[object Date]\"===Object.prototype.toString.call(e)}o.target=o.target||\"https://api.exponea.com\",o.file_path=o.file_path||o.target+\"/js/exponea.min.js\",r[n]=p([\"anonymize\",\"initialize\",\"identify\",\"getSegments\",\"update\",\"track\",\"trackLink\",\"trackEnhancedEcommerce\",\"getHtml\",\"showHtml\",\"showBanner\",\"showWebLayer\",\"ping\",\"getAbTest\",\"loadDependency\",\"getRecommendation\",\"reloadWebLayers\",\"_preInitialize\",\"_initializeConfig\"]),r[n].notifications=p([\"isAvailable\",\"isSubscribed\",\"subscribe\",\"unsubscribe\"]),r[n].segments=p([\"subscribe\"]),r[n][\"snippetVersion\"]=\"v2.7.0\",function(e,n,t){e[n][\"_\"+t]={},e[n][\"_\"+t].nowFn=Date.now,e[n][\"_\"+t].snippetStartTime=e[n][\"_\"+t].nowFn()}(r,n,\"performance\"),function(e,n,t,i,r,o){e[r]={sdk:e[i],sdkObjectName:i,skipExperiments:!!t.new_experiments,sign:t.token+\"/\"+(o.exec(n.cookie)||[\"\",\"new\"])[1],path:t.target}}(r,e,o,n,i,RegExp(\"__exponea_etc__\"+\"=([\\w-]+)\")),function(e,n,t){m(e.file_path,n,t)}(o,t,e),function(e,n,t,i,r,o,p){if(e.new_experiments){!0===e.new_experiments&&(e.new_experiments={});var l,f=e.new_experiments.hide_class||c,_=e.new_experiments.timeout||a,g=encodeURIComponent(o.location.href.split(\"#\")[0]);e.cookies&&e.cookies.expires&&(\"number\"==typeof e.cookies.expires||u(e.cookies.expires)?l=s(e.cookies.expires):e.cookies.expires.tracking&&(\"number\"==typeof e.cookies.expires.tracking||u(e.cookies.expires.tracking))&&(l=s(e.cookies.expires.tracking))),l&&l<new Date&&(l=void 0);var d=e.target+\"/webxp/\"+n+\"/\"+o[t].sign+\"/modifications.min.js?http-referer=\"+g+\"&timeout=\"+_+\"ms\"+(l?\"&cookie-expires=\"+Math.floor(l.getTime()/1e3):\"\");\"sync\"===e.new_experiments.mode&&o.localStorage.getItem(\"__exponea__sync_modifications__\")?function(e,n,t,i,r){t[r][n]=\"<\"+n+' src=\"'+e+'\"></'+n+\">\",i.writeln(t[r][n]),i.writeln(\"<\"+n+\">!\"+r+\".init && document.writeln(\"+r+\".\"+n+'.replace(\"/'+n+'/\", \"/'+n+'-async/\").replace(\"><\", \" async><\"))</'+n+\">\")}(d,n,o,p,t):function(e,n,t,i,r,o,s,a){o.documentElement.classList.add(e);var c=m(t,i,o);function p(){r[a].init||m(t.replace(\"/\"+i+\"/\",\"/\"+i+\"-async/\"),i,o)}function u(){o.documentElement.classList.remove(e)}c.onload=p,c.onerror=p,r.setTimeout(u,n),r[s]._revealPage=u}(f,_,d,n,o,p,r,t)}}(o,t,i,0,n,r,e),function(e,n,t){var i;e[n]._initializeConfig(t),(null===(i=t.experimental)||void 0===i?void 0:i.non_personalized_weblayers)&&e[n]._preInitialize(t),e[n].start=function(i){i&&Object.keys(i).forEach((function(e){return t[e]=i[e]})),e[n].initialize(t)}}(r,n,o)}(document,\"exponea\",\"script\",\"webxpClient\",window,{\n target: \"https://eu2-api.eng.bloomreach.com\",\n token: \"".concat(config_1.projectToken, "\",\n experimental: {\n non_personalized_weblayers: true,\n },\n track: {\n google_analytics: false,\n },\n });\n window.exponea.start();\n console.log('Bloomreach SDK initialized with official snippet');\n "); document.head.appendChild(script); // Track page view after initialization setTimeout(function () { if (window.exponea) { // Update customer properties with host information var customerData = { host: window.location.host, last_visit: new Date().toISOString(), url: window.location.href, referrer: document.referrer || 'direct', browser: navigator.userAgent, push_notifications_supported: _this.state.browserSupported }; window.exponea.update(customerData); console.log('Customer properties updated with host:', customerData); // Mark as initialized _this.setState({ isInitialized: true }, function () { var _a; // Set up notifications if needed if (_this.state.browserSupported && ((_a = config_1.notifications) === null || _a === void 0 ? void 0 : _a.requestPermissionOnLoad) && Notification.permission === 'default') { _this.requestNotificationPermission(); } }); } }, 1000); // Allow time for the SDK to initialize } } catch (error) { console.error('Error initializing SDK:', error); this.setState({ error: error }); } return [2 /*return*/]; }); }); }; NextBloomreachProvider.prototype.render = function () { var _this = this; if (!this.state.isClient) { return null; } if (this.state.error) { console.error('SDK initialization error:', this.state.error); return null; } return (react_1.default.createElement(BloomreachContext_1.BloomreachContext.Provider, { value: { isInitialized: this.state.isInitialized, hasConsent: this.state.hasConsent, browserSupported: this.state.browserSupported, setHasConsent: function (consent) { var _a, _b; _this.setState({ hasConsent: consent }); (_b = (_a = _this.props.config).onConsentGranted) === null || _b === void 0 ? void 0 : _b.call(_a); }, config: this.props.config } }, react_1.default.createElement(NotificationHandler_1.NotificationHandler, { onConsentGranted: function () { var _a, _b; _this.setState({ hasConsent: true }); (_b = (_a = _this.props.config).onConsentGranted) === null || _b === void 0 ? void 0 : _b.call(_a); }, onConsentDenied: function () { var _a, _b; _this.setState({ hasConsent: false }); (_b = (_a = _this.props.config).onConsentDenied) === null || _b === void 0 ? void 0 : _b.call(_a); } }), this.props.children)); }; return NextBloomreachProvider; }(react_1.default.Component)); exports.NextBloomreachProvider = NextBloomreachProvider;