{"id":20893,"date":"2020-09-15T08:05:22","date_gmt":"2020-09-15T08:05:22","guid":{"rendered":"https:\/\/ec2-54-72-10-141.eu-west-1.compute.amazonaws.com\/docs\/?post_type=knowledgebase&#038;p=20893"},"modified":"2026-03-25T21:20:17","modified_gmt":"2026-03-25T21:20:17","slug":"reference","status":"publish","type":"knowledgebase","link":"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/","title":{"rendered":"JavaScript SDK Reference"},"content":{"rendered":"\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>Our Javascript web client exposes various methods that can be used to deeply integrate your web application with Refiner. On this page, we&#8217;ll cover each method and provide sample code which you can use for your project.<\/p>\n\n\n\n<p>Before you can use the JavaScript SDK and its method, you&#8217;ll need to install it in your web application or on your website. To make the installation process as easy as possible for you, we are offering different options depending on what technology you are familiar with. The SDK can be installed in following ways:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/refiner.io\/docs\/kb\/install-client\/javascript\/\">Copy &amp; paste code snippet<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/refiner.io\/docs\/kb\/install-client\/google-tag-manager\/\">Google Tag Manager<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/refiner.io\/docs\/kb\/install-client\/npm-package\/\">NPM Package<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/refiner.io\/docs\/kb\/install-client\/wordpress-popup-survey-plugin\/\">WordPress Plugin<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"identify\">Identify &amp; track users<\/h2>\n\n\n\n<p>Identifying your users is most likely the first thing you want to do once you&#8217;ve successfully installed our client. While it&#8217;s possible to operate the client in anonymous mode, identifying your users will unlock many powerful features such as <a href=\"https:\/\/refiner.io\/docs\/kb\/reporting\/segments\/\">segmenting your users<\/a>, <a href=\"https:\/\/refiner.io\/docs\/kb\/widgets\/target-audience\/\">creating target audiences<\/a>, etc.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Identify users<\/h3>\n\n\n\n<p>The <em>identifyUser<\/em> call expect a unique identifier (&#8220;user ID&#8221;) or an email address for each user. We recommend to provide both values if possible.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('identifyUser', {\n    id: 'USER-ID-ABC-123', \/\/ Replace with your user ID\n    email: 'jane@awesome.com', \/\/ Replace with user Email\n    name: 'Jane Doe'\n});\n<\/pre>\n\n\n\n<p>The <em>identifyUser<\/em> method also lets you import additional user traits as described below.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"additional-traits\">Import user traits<\/h3>\n\n\n\n<p>Importing additional data points allows you to better <a href=\"https:\/\/refiner.io\/docs\/kb\/segmentation\/data-driven-segments\/\">segment and target<\/a> users in Refiner. <\/p>\n\n\n\n<p>Sending in additional traits is easy. All you need to do is to include the traits you wish to appear in Refiner to in the&nbsp;<em>identifyUser<\/em>&nbsp;call as shown below.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('identifyUser', {\n  id: 'USER-ID-ABC-123',\n  name: 'Jane Doe',\n  email: 'jane@awesome.com',\n  signed_up_at: '2020-04-26T17:58:14+02:00',\n  ...\n  custom_user_data: 'Some important data',\n  upgraded_at: '2021-05-05 17:12',\n  a_number: 42,\n  more_custom_user_data: 'Something even more important',\n  ...\n});<\/pre>\n\n\n\n<p>The following data types are supported:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Strings<\/strong>  &#8211; 10.000 characters max length<\/li>\n\n\n\n<li><strong>Integer numbers<\/strong>  &#8211; ranging from -2147483647 to 2147483647<\/li>\n\n\n\n<li><strong>Dates<\/strong> &#8211; ISO date format or Linux timestamp<\/li>\n<\/ul>\n\n\n\n<p>To import an integer number, please make sure that the value is not wrapped in quotes. Wrapping a number in quotes will result in a String value in Refiner.<\/p>\n\n\n\n<p>If you want to import dates, the identifier of your field needs to follow a certain pattern. As the JSON specification has no explicit way of declaring dates, we rely on the field identifier to determine if a value should be read as a date or a normal string. Our API is detecting dates if the attribute name ends with &#8220;_at&#8221; (e.g. created_at, upgraded_at, another_event_at, &#8230;) or &#8220;_date&#8221; (e.g. subscription_date, last_login_date, &#8230;).<\/p>\n\n\n\n<p>Refiner has a couple of <a href=\"https:\/\/refiner.io\/docs\/kb\/data-index\/user-traits\/#reserved\">reserved fields<\/a> you should be aware of. These fields can&#8217;t be overwritten or have a certain behaviour attached to them.<\/p>\n\n\n\n<p>You can also make use of <a href=\"#magic\">Magic Variables<\/a> to dynamically inject certain client related values as described further below.<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<h3 class=\"wp-block-heading\" id=\"locale\">Set user language<\/h3>\n\n\n\n<p>When using our centralized <a href=\"https:\/\/refiner.io\/docs\/kb\/settings\/multi-language-surveys\/\">translation interface<\/a> or <a href=\"https:\/\/refiner.io\/docs\/kb\/in-product-surveys\/target-audience\/#locale\">language targeting<\/a>, you can manually set the language of a user. If you don&#8217;t set the language, the preferred web-browser languages are used instead.<\/p>\n\n\n\n<p>The expected format of the locale variable is a comma separated list of two characters <a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes\" target=\"_blank\" rel=\"noreferrer noopener\">ISO 639-1 codes<\/a>.<\/p>\n\n\n\n<p>We recommend to call the <em>setLocale<\/em> method right before the <em>identifyUser<\/em> method.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ set one preferred language\n_refiner('setLocale', 'fr');\n\n\/\/ it is also possible to set multiple preferred languages\n_refiner('setLocale', 'fr,en,es');<\/pre>\n\n\n\n<p>As an alternative to the &#8216;setLocale&#8217; method, it is also possible to provide a &#8220;locale&#8221; trait in an additional option object when identifying a user.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('identifyUser', {\n  id: 'your-user-id',\n  a_trait: 'trait data'\n}, {\n  locale: 'fr'\n});<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"country\">Set user country<\/h3>\n\n\n\n<p>When using our <a href=\"https:\/\/refiner.io\/docs\/kb\/in-product-surveys\/target-audience\/#Country\">country targeting<\/a> option, the country of a user is by default detected automatically using their IP address. You can choose to manually set the country of a user and thus deactivate the IP address lookup. <\/p>\n\n\n\n<p>The expected format of the country variable is a two characters <a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes\" target=\"_blank\" rel=\"noreferrer noopener\">ISO 3166 country code<\/a>.<\/p>\n\n\n\n<p>We recommend to call the <em>setCountry<\/em> method right before the <em>identifyUser<\/em> method.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('setCountry', 'fr');<\/pre>\n\n\n\n<p>As an alternative to the &#8216;setCountry&#8217; method, you can also provide a &#8220;country&#8221; trait in an additional option object when identifying a user.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('identifyUser', {\n  id: 'your-user-id',\n  a_trait: 'trait data'\n}, {\n  locale: 'fr',\n  country: 'fr'\n});<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"track-event\">Track events<\/h3>\n\n\n\n<p><a href=\"https:\/\/refiner.io\/docs\/kb\/segmentation\/tracking-user-events\/\">Tracking user events<\/a> with our SDK is easy. Once our JavaScript client was loaded and an <em>identifyUser<\/em> call was performed, you can track events with a single line of code as shown above.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('trackEvent', 'MyCustomEventName');<\/pre>\n\n\n\n<p>Please note that we are only tracking the occurrence of an event. It is not possible to attach attributes to an event.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"session\">Start new session<\/h3>\n\n\n\n<p>The start time of the  current user session can be used as the reference time in the <a href=\"https:\/\/refiner.io\/docs\/kb\/in-product-surveys\/trigger-events\/#time-delay\">Time Delay<\/a> and <a href=\"https:\/\/refiner.io\/docs\/kb\/in-product-surveys\/trigger-events\/#tracked-event\">Tracked Event<\/a> survey trigger.<\/p>\n\n\n\n<p>We try to automatically detect when a user starts a new session in your application. A new user session is detected when a user returns to your application after at least one hour of inactivity.<\/p>\n\n\n\n<p>You can choose inform Refiner that a new session started with the <em>startSession<\/em> method as shown below. You can call this method for example right after a user logs in to your application.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('startSession');<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"reset\">Reset users<\/h3>\n\n\n\n<p>It&#8217;s possible to reset user identifiers that were set through the &#8220;<a href=\"https:\/\/refiner.io\/docs\/kb\/install\/javascript-integration\/#identify\">identifyUser<\/a>&#8221; command. If you are using Refiner in a Single Page Application (SPA), we recommend executing the following command after a user logs out from your app.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('resetUser');<\/pre>\n\n\n\n<p>Please note: Resetting the user identity sets the client back into &#8220;<a href=\"https:\/\/refiner.io\/docs\/kb\/install\/javascript\/#anonymous-mode\">Anonymous Mode<\/a>&#8220;. However, an <a href=\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/web-storage-cookies\/\">anonymous local storage identifier<\/a> linked to the user will persist and our API will continue to recognize the user. You might still see an &#8220;last seen at&#8221; for the user even if they are logged out. To stop all communication with our servers, we recommend to also execute the &#8220;<a href=\"https:\/\/refiner.io\/docs\/kb\/install\/javascript-integration\/#stop-pinging\">stopPinging<\/a>&#8221; command.<\/p>\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"attach\">Attach data to responses<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Add hidden fields<\/h3>\n\n\n\n<p>Our Javascript client allows you to attach additional data to the survey responses.<\/p>\n\n\n\n<p>Attaching data to your survey responses is like a hidden field feature in traditional survey tools. However, you don&#8217;t need to create a field in your Refiner dashboard. <\/p>\n\n\n\n<p>To attach additional data to survey response, execute the following command including the data you want to attach before the survey is shown. <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('addToResponse', {\n  more_data: \"Hello!\"\n});<\/pre>\n\n\n\n<p>You can execute the command either on page load, or dynamically right before a survey is triggered, for example by leveraging the &#8220;<a href=\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/#callbacks\">onBeforeShow<\/a>&#8221; callback function.<\/p>\n\n\n\n<p>You can also make use of <a href=\"#magic\">Magic Variables<\/a> to dynamically inject certain client related values when survey responses are stored as described further below.<\/p>\n\n\n\n<p>Please note that common information like the current URL, the user language, etc. can also be attached to survey responses using our built-in <a href=\"https:\/\/refiner.io\/docs\/kb\/data-index\/data-settings\/#metadata\">metadata collection<\/a> option.<\/p>\n\n\n\n<p>The provided data is persistent throughout all upcoming survey responses that happen until the page is reloaded. If you expect additional survey responses to which you don&#8217;t want to attach the additional data, you can reset the data or overwrite it with different data. <\/p>\n\n\n\n<p>To reset the attached data, execute the method and provide a <em>null<\/em> value. You can use the &#8220;onComplete&#8221; callback to reset the data after a survey was submitted.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('onComplete', function(formId, responseData) {\n  _refiner('addToResponse', null);\n});<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"tag-response\">Tag response<\/h3>\n\n\n\n<p>You can <a href=\"https:\/\/refiner.io\/docs\/kb\/reporting\/response-tagging\/\">tag survey responses<\/a> programmatically using the tagResponse method. You can define up to ten tags that will be associated with all upcoming survey responses. <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('tagResponse', ['tag1', 'tag2']);<\/pre>\n\n\n\n<p>To reset tagging,  you can set the tags to <em>null<\/em>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('tagResponse', null);<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"show-ad-hoc\">Show and hide survey ad-hoc<\/h2>\n\n\n\n<p>Sometimes you might want to show or hide a survey programmatically, directly from your application&#8217;s JavaScript code. The <a href=\"https:\/\/refiner.io\/docs\/kb\/in-product-surveys\/trigger-events\/#manual\">Manual survey trigger<\/a> allows you do exactly this.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"show-survey\">Show survey<\/h3>\n\n\n\n<p>Once the JavaScript client was loaded and an&nbsp;identifyUser&nbsp;call was performed, you can launch a survey with the code below.<\/p>\n\n\n\n<p>The ID of your form can be found in the survey editor under &#8220;Targeting &amp; Launch Behaviour&nbsp; &gt; Trigger Event &gt; Manually&#8221;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('showForm', 'SURVEY_ID');<\/pre>\n\n\n\n<p><em>Please note:<\/em> The showForm function takes other trigger restriction into account and you might receive a &#8220;already completed&#8221; or similar messages.<\/p>\n\n\n\n<p>To circumvent this, you can add an additional boolean parameter which then forces the survey view.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('showForm', 'SURVEY_ID', true);<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"close-survey\">Close survey<\/h3>\n\n\n\n<p>When it comes to hiding a survey programmatically, you can either call a <em>closeForm<\/em> or <em>dismissForm<\/em> method. Both methods close a survey immediately and there is no difference between the two from a user&#8217;s point of view. <\/p>\n\n\n\n<p>There is however a difference in what kind of information is sent to our backend API. The method <em>dismissForm<\/em> will ping our server and we&#8217;ll store a <em>dismissed_at<\/em> timestamp for the user.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('dismissForm');<\/pre>\n\n\n\n<p>The <em>closeForm<\/em> method won&#8217;t send any information to our server and just closes the survey silently. <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('closeForm');<\/pre>\n\n\n\n<p>Calling <em>closeForm<\/em> and <em>dismissForm<\/em> when no survey is visible at the time of calling has no effect. You can safely call the methods as a precaution mechanism to make sure that all surveys are closed at a certain time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Advanced options<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"callbacks\">Callback functions<\/h3>\n\n\n\n<p>Registering callback functions allows you to execute any JavaScript code at specific moments in the lifecycle of a survey. For example, redirect a user to a new page once they completed a survey.<\/p>\n\n\n\n<p>The following callback hooks are available:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-regular\"><table><tbody><tr><td><strong>Method<\/strong><\/td><td><strong>Description<\/strong><\/td><\/tr><tr><td><em>onBeforeShow<\/em><\/td><td>Gets called right before a survey is supposed to be shown.<\/td><\/tr><tr><td><em><em>onClose<\/em><\/em><\/td><td>Gets called when the survey widgets disappears from the screen.<\/td><\/tr><tr><td><em>onComplete<\/em><\/td><td>Gets called when the user completed (submitted) the entire survey.<\/td><\/tr><tr><td><em>onDismiss<\/em><\/td><td>Gets called when the user dismissed a survey by clicking on the \u201cx\u201d in the top right corner.<\/td><\/tr><tr><td><em>onError<\/em><\/td><td>Gets called when a request from the client to our backend API fails.<\/td><\/tr><tr><td><em>onNavigation<\/em><\/td><td>Gets called for each step when the user responds to questions or navigates through the survey.<\/td><\/tr><tr><td><em>onRequestResponse<\/em><\/td><td>Gets called whenever the client receives a response from the backend API.<\/td><\/tr><tr><td><em>onShow<\/em><\/td><td>Gets called when a survey widget becomes visible to your user.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Registering callback functions is done as shown in the code example below.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('onBeforeShow', function(formId, formConfig, next) {\n  console.log('Survey ' + formId + ' is supposed to be shown');\n  console.log(formConfig);\n  if (formId === 'ABC') {\n    console.log('Abort mission');\n    return false;\n  }\n  console.log('Continue and show survey');\n  next();\n});\n\n_refiner('onClose', function(formId) {\n console.log('Survey ' + formId + ' was closed');\n});\n\n_refiner('onComplete', function(formId, responseData) {\n  console.log('Survey ' + formId + ' was submitted');\n  console.log(responseData);\n});\n\n_refiner('onDismiss', function(formId) {\n console.log('Survey ' + formId + ' was dismissed');\n});\n\n_refiner('onNavigation', function(formId, formElement, progress) {\n  console.log(formId);\n  console.log(formElement);\n  console.log(progress);\n});\n\n_refiner('onRequestResponse', function(httpCode, functionName, responseData) {\n  console.log(httpCode);\n  console.log(functionName);\n  console.log(responseData);\n});\n\n_refiner('onShow', function(formId) {\n  console.log('Survey ' + formId + ' was shown');\n});\n\n\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"magic\">Magic Variables<\/h3>\n\n\n\n<p>Magic Variables allow you to add contextual data to survey responses or user profiles without needing to code any Javascript. You can use Magic Variables to store things like the URL, information about a user&#8217;s web browser, or their IP address alongside survey responses.<\/p>\n\n\n\n<p>Magic Variables can be used when <a href=\"#identify\">identifying a user<\/a> or <a href=\"#attach\">attaching data to survey responses<\/a> as shown in the code sample below. <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('identifyUser', {\n  id: 'USER-ID-ABC-123',\n  country_code: '__COUNTRY__',\n});\n\n_refiner('addToResponse', {\n  url: '__CURRENT_URL__',\n  browser_name: '__WEB_BROWSER__',\n});<\/pre>\n\n\n\n<p>Here is the list of all Magic Variables supported by the JavaScript SDK:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-regular\"><table><tbody><tr><td><strong>Variable<\/strong><\/td><td><strong>Description<\/strong><\/td><\/tr><tr><td><em>__COUNTRY_CODE__<\/em><\/td><td>The country code of the user as described <a href=\"#country\">here<\/a><\/td><\/tr><tr><td><em>__CURRENT_URL__<\/em><\/td><td>The current URL of the user<\/td><\/tr><tr><td><em>__IP_ADDRESS__<\/em><\/td><td>The current IP address of the user<\/td><\/tr><tr><td><em>__LOCALE__<\/em><\/td><td>The locale value as described <a href=\"#locale\">here<\/a><\/td><\/tr><tr><td><em>__WEB_BROWSER__<\/em><\/td><td>The web browser name of the user (e.g. Chrome 27)<\/td><\/tr><tr><td><em>__WEB_DEVICE_OS__<\/em><\/td><td>The operating system of the user (e.g. Mac OS)<\/td><\/tr><tr><td><em>__WEB_DEVICE_TYPE__<\/em><\/td><td>The device type of the user (e.g. desktop, tablet, mobile)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"stop-pinging\">Disable &amp; enable client<\/h3>\n\n\n\n<p>You can instruct the client to stop querying our servers and prevent any surveys from being displayed.<\/p>\n\n\n\n<p>When &#8216;disableClient&#8217; is invoked, the SDK immediately stops any communication with the backend API and currently open surveys will be closed.<\/p>\n\n\n\n<p>This allows you to programmatically suspend survey activity &#8211; for example, in critical areas of your app, during maintenance windows, or based on user consent preferences.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('disableClient');<\/pre>\n\n\n\n<p>The client remains disabled until it is explicitly re-enabled using the following command:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('enableClient');<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"group-users\">Group users<\/h3>\n\n\n\n<p>Most B2B SaaS applications are running on an account based system, where multiple users are grouped under one account (think &#8220;Team Accounts&#8221;, &#8220;Organization&#8221;, or &#8220;Company&#8221;). <\/p>\n\n\n\n<p>Refiner supports &#8220;N users = 1 account&#8221; relationships out of the box. You can tell Refiner to which account a user belongs by adding an account object in the <em>identifyUser<\/em> call. <\/p>\n\n\n\n<p>You can also include account level data inside the account object (see above) in the same way you would for user level data.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('identifyUser', {\n  id: 'USER-ID-ABC-123',\n  email: 'jane@awesome.com',\n  name: 'Jane Doe',\n  ...\n  account: {\n    id: 'ACCOUNT-ID-ABC-12345',\n    name: 'Awesome Inc.',\n    some_account_data: 'something',\n    a_date_at: '2022-01-31'\n    ...\n  }\n});<\/pre>\n\n\n\n<p><em>Please note:<\/em> Refiner supports N:1 group relationships, where one user belongs to one group (company, account, &#8230;). If your app is running on an N:N relationship model where one user belongs to multiple groups, we recommend to keep things simple and work on a user level only.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"signature\">Verify identity<\/h3>\n\n\n\n<p>If you are using the option <a href=\"https:\/\/refiner.io\/docs\/kb\/settings\/identity-verification\/\">Identity Verification<\/a> security mechanism, you can pass the computed signature in an additional object as shown below. <\/p>\n\n\n\n<p>Please make sure that you are passing the signature and not the secret key.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('identifyUser', {\n    id: 'USER-ID-ABC-123', \/\/ Replace with your user ID\n    email: 'jane@awesome.com', \/\/ Replace with user Email\n    name: 'Jane Doe'\n}, {\n    signature: COMPUTED_SIGNATURE\n});\n<\/pre>\n\n\n\n<p>If your app loads user data asynchronously, you can include the computed signature in the response from the server alongside other user data. Please make sure to always compute the signature on the backend and never client-side in the frontend code.<\/p>\n\n\n\n<p>You can verify that the signature was computed correctly by opening the Developer Console of your web browser. If you see requests to our server failing with a 403 code, your signature is not calculated correctly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"dark-mode\">Handle Dark-Mode<\/h3>\n\n\n\n<p>If your application has a &#8220;dark mode&#8221;, our survey widget might show an opaque background in some browsers. It is a <a href=\"https:\/\/fvsch.com\/transparent-iframes\">known issue<\/a> that iframes are using opaque background when the color scheme of an HTML document is set to dark-mode and we are working on a permanent fix for this issue. For a quick solution, please add the following CSS to your application code when in dark mode:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"css\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#refiner-widget-frame { color-scheme: light; }<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"add-to-user\">Deferred user identification<\/h3>\n\n\n\n<p>If you want to add traits to a user object, we usually recommend to user <a href=\"#identify\">identifyUser<\/a> method as described above. As an alternative, you can also provide user traits through the addToUser method. <\/p>\n\n\n\n<p>The main difference between the two methods is that identifyUser creates a user profile in Refiner immediately when the SDK is loaded. The method addToUser does not create a user profile immediately. Traits are kept locally und are sent to Refiner when a survey is shown to the user.<\/p>\n\n\n\n<p>Unlike the identifyUser method, no user identifier (ID or email) is required for the addToUser method. You can use this method to add user traits when you are operating the JavaScript SDK in anonymous user mode. If you choose to provide a &#8220;id&#8221; or &#8220;email&#8221; trait, it will be interpreted as a user identifier.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('addToUser', {\n    a_user_traits: 'something',\n    another_user_trait: 'something else',\n});\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"write-operation\">Set data write operation<\/h3>\n\n\n\n<p>By default, all user data imported to Refiner with the &#8220;identifyUser&#8221; or &#8220;setUser&#8221; method call (see above) is appended to the user recorded. If you stop including a specific user trait in your identifyUser method, it will still remain in the user record in your Refiner environment.<\/p>\n\n\n\n<p>It is possible to switch the write operation from &#8220;<strong>append<\/strong>&#8221; to &#8220;<strong>replace<\/strong>&#8221; if you want to change this behaviour. Once switched to &#8220;replace&#8221;, only the user traits included in the last &#8220;identifyUser&#8221; call are stored in the user object in Refiner.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('setWriteOperation', 'replace');\n<\/pre>\n\n\n\n<p>As an alternative to the &#8216;setWriteOperation&#8217; method, you can also provide a &#8220;write_operation&#8221; trait in an additional option object when identifying a user.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">_refiner('identifyUser', {\n  id: 'your-user-id',\n  a_trait: 'trait data'\n}, {\n  locale: 'fr',\n  country: 'fr',\n  write_operation: 'replace'\n});<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"client-storage\">Set client storage method<\/h3>\n\n\n\n<p>By default, the JavaScript SDK stores user identifiers and timestamps in <a href=\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/web-storage-cookies\/\">localStorage<\/a>. If localStorage is unavailable, it falls back to cookies.<\/p>\n\n\n\n<p>If your compliance requirements prohibit persistent storage, you can switch to sessionStorage, which is cleared when the browser window is closed:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">refiner('setClientStorageMethod', 'sessionStorage');<\/pre>\n\n\n\n<p>Call this method as early as possible, ideally immediately after initializing the SDK.<\/p>\n\n\n\n<p>Available options are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>localStorageFallbackCookies (default) &#8211; uses localStorage, with cookies as a fallback<\/li>\n\n\n\n<li>localStorage &#8211; persists data across browser sessions<\/li>\n\n\n\n<li>sessionStorage &#8211; resets data when the browser window is closed<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Our Javascript web client exposes various methods that can be used to deeply integrate your web application with Refiner. On this page, we&#8217;ll cover each method and provide sample code which you can use for your project. Before you can use the JavaScript SDK and its method, you&#8217;ll need to install it in your [&#8230;]<\/p>\n<p><a class=\"btn btn-secondary understrap-read-more-link\" href=\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/\">Read More&#8230;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","template":"","knowledgebase_tag":[],"class_list":["post-20893","knowledgebase","type-knowledgebase","status-publish","hentry","knowledgebase_cat-javascript-client"],"featured_image_urls_v2":{"full":"","thumbnail":"","medium":"","medium_large":"","large":"","1536x1536":"","2048x2048":"","ab-block-post-grid-landscape":"","ab-block-post-grid-square":"","gb-block-post-grid-landscape":"","gb-block-post-grid-square":""},"post_excerpt_stackable_v2":"<p>Introduction Our Javascript web client exposes various methods that can be used to deeply integrate your web application with Refiner. On this page, we&#8217;ll cover each method and provide sample code which you can use for your project. Before you can use the JavaScript SDK and its method, you&#8217;ll need to install it in your web application or on your website. To make the installation process as easy as possible for you, we are offering different options depending on what technology you are familiar with. The SDK can be installed in following ways: Copy &amp; paste code snippet Google Tag&hellip;<\/p>\n","category_list_v2":"","author_info_v2":{"name":"Moritz Dausinger","url":"https:\/\/refiner.io\/docs\/author\/user\/"},"comments_num_v2":"0 comments","acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v23.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>JavaScript SDK Reference<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"JavaScript SDK Reference\" \/>\n<meta property=\"og:description\" content=\"Introduction Our Javascript web client exposes various methods that can be used to deeply integrate your web application with Refiner. On this page, we&#8217;ll cover each method and provide sample code which you can use for your project. Before you can use the JavaScript SDK and its method, you&#8217;ll need to install it in your [...]Read More...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/\" \/>\n<meta property=\"og:site_name\" content=\"Refiner Documentation\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-25T21:20:17+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/\",\"url\":\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/\",\"name\":\"JavaScript SDK Reference\",\"isPartOf\":{\"@id\":\"https:\/\/refiner.io\/docs\/#website\"},\"datePublished\":\"2020-09-15T08:05:22+00:00\",\"dateModified\":\"2026-03-25T21:20:17+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/refiner.io\/docs\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JavaScript SDK Reference\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/refiner.io\/docs\/#website\",\"url\":\"https:\/\/refiner.io\/docs\/\",\"name\":\"Refiner Documentation\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/refiner.io\/docs\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/refiner.io\/docs\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/refiner.io\/docs\/#organization\",\"name\":\"Refiner Documentation\",\"url\":\"https:\/\/refiner.io\/docs\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/refiner.io\/docs\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/refiner.io\/docs\/wp-content\/uploads\/2022\/11\/cropped-Group-8.png\",\"contentUrl\":\"https:\/\/refiner.io\/docs\/wp-content\/uploads\/2022\/11\/cropped-Group-8.png\",\"width\":400,\"height\":61,\"caption\":\"Refiner Documentation\"},\"image\":{\"@id\":\"https:\/\/refiner.io\/docs\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"JavaScript SDK Reference","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/","og_locale":"en_US","og_type":"article","og_title":"JavaScript SDK Reference","og_description":"Introduction Our Javascript web client exposes various methods that can be used to deeply integrate your web application with Refiner. On this page, we&#8217;ll cover each method and provide sample code which you can use for your project. Before you can use the JavaScript SDK and its method, you&#8217;ll need to install it in your [...]Read More...","og_url":"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/","og_site_name":"Refiner Documentation","article_modified_time":"2026-03-25T21:20:17+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/","url":"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/","name":"JavaScript SDK Reference","isPartOf":{"@id":"https:\/\/refiner.io\/docs\/#website"},"datePublished":"2020-09-15T08:05:22+00:00","dateModified":"2026-03-25T21:20:17+00:00","breadcrumb":{"@id":"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/refiner.io\/docs\/kb\/javascript-client\/reference\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/refiner.io\/docs\/"},{"@type":"ListItem","position":2,"name":"JavaScript SDK Reference"}]},{"@type":"WebSite","@id":"https:\/\/refiner.io\/docs\/#website","url":"https:\/\/refiner.io\/docs\/","name":"Refiner Documentation","description":"","publisher":{"@id":"https:\/\/refiner.io\/docs\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/refiner.io\/docs\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/refiner.io\/docs\/#organization","name":"Refiner Documentation","url":"https:\/\/refiner.io\/docs\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/refiner.io\/docs\/#\/schema\/logo\/image\/","url":"https:\/\/refiner.io\/docs\/wp-content\/uploads\/2022\/11\/cropped-Group-8.png","contentUrl":"https:\/\/refiner.io\/docs\/wp-content\/uploads\/2022\/11\/cropped-Group-8.png","width":400,"height":61,"caption":"Refiner Documentation"},"image":{"@id":"https:\/\/refiner.io\/docs\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/refiner.io\/docs\/wp-json\/wp\/v2\/knowledgebase\/20893","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/refiner.io\/docs\/wp-json\/wp\/v2\/knowledgebase"}],"about":[{"href":"https:\/\/refiner.io\/docs\/wp-json\/wp\/v2\/types\/knowledgebase"}],"author":[{"embeddable":true,"href":"https:\/\/refiner.io\/docs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/refiner.io\/docs\/wp-json\/wp\/v2\/comments?post=20893"}],"version-history":[{"count":195,"href":"https:\/\/refiner.io\/docs\/wp-json\/wp\/v2\/knowledgebase\/20893\/revisions"}],"predecessor-version":[{"id":28373,"href":"https:\/\/refiner.io\/docs\/wp-json\/wp\/v2\/knowledgebase\/20893\/revisions\/28373"}],"wp:attachment":[{"href":"https:\/\/refiner.io\/docs\/wp-json\/wp\/v2\/media?parent=20893"}],"wp:term":[{"taxonomy":"knowledgebase_tag","embeddable":true,"href":"https:\/\/refiner.io\/docs\/wp-json\/wp\/v2\/knowledgebase_tag?post=20893"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}