Integration Guide
Definition
This document outlines the step-by-step instructions on how to utilize web SDK wrappers for various configurations (Settings, Tracker, etc.) and for each individual wrapper (React, Typescript, Node, etc.).
Pulse loader configuration
To initialize the Pulse SDK and load the required scripts (refer to the wrapper section for more details), add the following scripts to the head section of your page's HTML file.
<script type="module" src="https://optifyr.com/pulse/{{appName}}/module/pulse.js?include=settings,tracker&prefetch=tag1,tag3&ur=userRole1,userRole2&version=your_app_version" async fetchpriority="high" onerror="window.pulseFailedToLoad = true; window.dispatchEvent(new Event('pulseLoadFailed'));"></script>
<script nomodule src="https://optifyr.com/pulse/{{appName}}/nomodule/pulse.js?include=settings,tracker&prefetch=tag1,tag3&ur=userRole1,userRole2&version=your_app_version" async fetchpriority="high" onerror="window.pulseFailedToLoad = true; window.dispatchEvent(new Event('pulseLoadFailed'));"></script>
Note: Replace {{appName}} with the actual name of your application.
Note: If you're running the application in a development or staging environment, simply prefix 'dev.' or 'stage.' to 'optifyr.com'. This will improve your testing capabilities.
<script type="module" src="https://dev.optifyr.com/pulse/{{appName}}/module/pulse.js?include=settings,tracker&prefetch=tag1,tag3&ur=userRole1,userRole2&version=your_app_version" async fetchpriority="high" onerror="window.pulseFailedToLoad = true; window.dispatchEvent(new Event('pulseLoadFailed'));"></script>
<script nomodule src="https://dev.optifyr.com/pulse/{{appName}}/nomodule/pulse.js?include=settings,tracker&prefetch=tag1,tag3&ur=userRole1,userRole2&version=your_app_version" async fetchpriority="high" onerror="window.pulseFailedToLoad = true; window.dispatchEvent(new Event('pulseLoadFailed'));"></script>
Important Note: Utilize the async modifier for the script, and if you have previously included the defer modifier, kindly remove it.
If you choose to skip this step, the script will be loaded by the wrapper during the next phase of wrapper initialization. Preloading the script significantly improves performance and page readiness.
If you only want to use either the settings SDK or the tracker SDK, you can specify the desired SDK in the query parameter of the URL. For example, to include only the settings SDK, use include=settings. Similarly, to include only the tracker SDK, use include=tracker.
Furthermore, you can prefetch settings needed for the page by passing tags in the query parameter of the URL. For instance, if you require settings with tags "tag1" and "tag3", use prefetch=tag1,tag3. This will ensure that the necessary settings are fetched and available when the page loads.
Note: User Role based segmentation can be accessed from version 1.50.0 onward.
To enable user role based segmentation within the settings SDK, include the user role as a query parameter in the URL. For example, if the user roles are 'userRole1, userRole2' append 'ur=userRole1,userRole2' to the query parameters.
Ensure that you update the wrapper version to at least 1.48.3 for all projects utilizing the root component or placing it on the same page before adding this script. Failure to do so may result in a script error appearing in the console.
Please make sure to follow these instructions to ensure the correct functioning of WEB SDK.
What is a wrapper
An SDK wrapper is a technology-specific minimalistic SDK, that exposes the bare minimum functionality needed by the WEB SDK, hiding all the complexity and loading details from the client, and provides easy-to-use APIs to get the requested configuration, more on the relation between the wrappers and SDKs, and the architecture can be found here.
Wrappers
Artifact access configuration for local environments
- Make sure you have Reporter role in gitlab for pulse-web project
- Add these lines to your .npmrc file
@pulse:registry=https://gitlab.com/api/v4/projects/23778878/packages/npm/
always-auth=true
Artifact access configuration for CI pipelines
@Pulse/Browser (TypeScript)
Installation
npm i –save @pulse/browser
Initialization
The browser package efficiently loads the necessary scripts and bundles based on the configurations requested by the client during initialization. If preloading has already occurred, this step will be skipped.
import { initializeScoped } from "@pulse/browser";
const pulse = initializeScoped({
app: "picsart.com",
defaults: {}, // key-value pair of default values
remoteSettingEnabled: true,
version: "your_app_version",
});
Input
app: the name of the application/client using the SDK, which can not be changed after initialization.
defaults: Dictionary of default settings.
remoteSettingEnabled: As of SDK version 1.47.7, the remoteSettingEnabled configuration is enabled by default. If you decide to set it to false, remote setting calls will be disabled, and the SDK will exclusively utilize the client's default values.
version: You can use this approach to let the SDK know your app's version. Then, whenever events are triggered, the app version will be included in the data for each event.
Settings SDK
The settings SDK object contains methods to retrieve settings. When used and passed the tag and name, it will return a promise that resolves to the requested settings, or the default value in case an error or timeout occurs.
import { initializeScoped } from "@pulse/browser";
const pulse = initializeScoped({
app: "your application name",
defaults: {}, // key-value pair of default values
remoteSettingEnabled: true,
});
const setting1: Promise<T> = pulse.observe < T > { tag: "tag", name: "name" };
const settings2: Promise<SettingList> = pulse.observe(
"anotherTag",
"anotherName"
);
The service will resort to defaults if:
When
initializeScopedis called, it will initiate the loading of the sdk bundle in the browser, ifpulse.observe('tag', 'name')is called before the loading is finished and the sdk is ready to use, the service will wait for a short timeout for the sdk to be ready, otherwise resorts to default, till the sdk is fully loaded under the hood.Loading or initialization of the underlying sdk has failed, the sdk will resort to default, and keep trying under the hood to
reloadthe sdk.If the network request to get the settings has gotten over a specific amount of time based on user connection.
Connection Type Timeout slow 2g 45.000ms 2g 27.500ms 3g 9.500ms 4g 3.000ms default 3.000ms
Tracker SDK
The tracker SDK provides methods to track events and manage state. You can use the dataLayer public array to publish events as follows:
// Using dataLayer (recommended for automatic tracking)
dataLayer.push(
{
pulse: "state",
user_id: 7733339543522,
},
{
pulse: "event",
event: "upload_done",
parameters: { size: 12000 },
}
);
// Or using the pulse instance directly
pulse.event({
event: "upload_done",
parameters: { size: 12000 },
});
pulse.set({ user_id: 7733339543522 });
And if the tracker isn't fully loaded at the moment of publish, it will pick up all the queued events inside the dataLayer once it is, so no events will be lost.
@Pulse/React
Installation
npm i –save @pulse/react
Initialization
@pulse/react operates under the hood using the context api, and exposes a provider component that takes the initialization config
import { PulseProvider } from '@pulse/react';
const Shell = () => (
<PulseProvider
app='your application name'
defaults={{}}
remoteSettingEnabled={true}
version='your application version'
>
{...rest of application components}
</PulseProvider>
);
const root = createRoot(document.getElementById('app-root')!);
root.render(<Shell />);
Input (feel free to skip this section if you have gone over @pulse/browser)
app: the name of the application/client using the sdk, which cannot be changed after initialization.
defaults: the default values for the settings that the sdk will resort to in case of failures or delays.
remoteSettingEnabled: by default, the configuration value is set to true, indicating that you will receive fresh settings. If you do not wish to receive fresh settings, you can change this value to false.
version: you can use this approach to let the SDK know your app's version. Then, whenever events are triggered, the app version will be included in the data for each event.
Note: The application version supplied through the prefetch script takes precedence.
Settings SDK
Settings SDK exposes hooks to retrieve the data:
import { usePulseSettings, usePulseState } from "@pulse/react";
const SomeComponent = () => {
const { loading, settings, error, hasError } = usePulseSettings({
tag: string,
name: string,
default: any,
});
onst { loading, segments, error, hasError } = usePulseSegments();
const { loading, experiments, error, hasError } = usePulseExperiments();
// OR
const { loading, settings, error, hasError, get } = useLazyPulseSettings(
{ tag: string, name: string, updateSettingChange: boolean }
);
const { loading, segments, error, hasError, get } = useLazyPulseSegments();
const { loading, experiments, error, hasError } = useLazyPulseExperiments();
const { loading, state, error, hasError } = usePulseState();
return (
<>
{hasError && <div>error</div>}
{settings && <div>{JSON.stringify(settings)}</div>}
{state && <div>{JSON.stringify(state)}</div>}
{experiments && <div>{JSON.stringify(experiments)}</div>}
</>
);
};
Tracker SDK
For the tracker SDK, you can use the dataLayer array to publish events, same as the browser package mentioned above:
// Using dataLayer (recommended for automatic tracking)
dataLayer.push(
{
pulse: "state",
user_id: 7733339543522,
},
{
pulse: "event",
event: "upload_done",
parameters: { size: 12000 },
}
);
Events verification
To make sure you have successfully integrated the Pulse SDK and your events get fired as expected, visit the tools debugger (choose the appropriate application and move to the debugger page) and enable the debug mode in your application by executing the following command in your browser console:
pulse.tracker.queue.batchQueue.transport.debug.enable("debugger");
Alternatively, append the query parameter to the URL in your browser's address bar debug-leuid=true
If your application is running inside an iFrame hosted on other pages, make sure to run the command in the context of the iFrame where the sdk is integrated.