Browser SDK Setup
Create a SafetyKit Webapp SDK session and load the returned browser script.
The SafetyKit Browser SDK (Beta) collects browser telemetry that SafetyKit uses when evaluating user sessions. Integrating it has two parts: your server creates a SafetyKit session token, and a small browser snippet loads the SafetyKit-hosted script with that token.
Server Setup
Section titled “Server Setup”Create a SafetyKit Webapp SDK session from server-side code before rendering pages that load the browser SDK. Keep your SafetyKit API key on the server; see Authentication for where to find your API keys. The Browser SDK (Beta) API is authenticated with your normal SafetyKit Bearer token and is served from diagnostics.safetykit.com.
The integration should fail open: if session creation fails, times out, or returns an invalid response, render the page without the browser SDK.
Install the SDK:
npm install safetykitCreate the session before rendering HTML pages, for example in an Express middleware. The timeout option is in milliseconds.
import { createHash } from "node:crypto";import Safetykit from "safetykit";import type { NextFunction, Request, Response } from "express";
const safetykit = new Safetykit({ apiKey: process.env.SAFETYKIT_API_KEY, timeout: 2000,});
export async function setSafetykitWebappSession( req: Request, res: Response, next: NextFunction,) { res.locals.safetykitWebappSession = await createSafetykitWebappSession(req); next();}
async function createSafetykitWebappSession(req: Request) { if (req.method !== "GET" || !req.accepts("html")) return null;
// req.user assumes an auth middleware such as Passport. Replace these two // values with however your app identifies the current user and session. const customerUserId = req.user?.id?.toString(); const customerSessionHash = currentSessionHash(req);
const params = customerUserId ? { customer_user_id: customerUserId, customer_session_hash: customerSessionHash, } : customerSessionHash ? { customer_session_hash: customerSessionHash } : null;
if (!params) return null;
try { return await safetykit.clientSessions.createSession(params); } catch (error) { if (error instanceof Safetykit.SafetykitError) { // Fail open: log the error and render the page without the browser SDK. return null; } throw error; }}
function currentSessionHash(req: Request): string | undefined { // req.sessionID assumes express-session. Send a stable hash of your session // ID, never the raw session or cookie value. if (!req.sessionID) return undefined; return createHash("sha256").update(req.sessionID).digest("hex");}Register the middleware before your page routes:
app.use(setSafetykitWebappSession);See the clientSessions.createSession API reference for the full TypeScript method signature, request parameters, and response fields.
Install the SDK by adding it to your Gemfile and running bundle install. The gem is named safetykit but is required as safety_kit:
gem "safetykit", require: "safety_kit"Create the session before rendering HTML pages, for example in a Rails controller. The timeout option is in seconds.
require "safety_kit"
class ApplicationController < ActionController::Base before_action :set_safetykit_webapp_session, if: -> { request.get? && request.format.html? }
private
def set_safetykit_webapp_session @safetykit_webapp_session = create_safetykit_webapp_session end
def create_safetykit_webapp_session session_params = { customer_user_id: current_user&.id&.to_s, customer_session_hash: current_session_hash, }.compact
return nil if session_params.empty?
safetykit_client.client_sessions.create_session(body: session_params) rescue SafetyKit::Errors::APIError nil end
def safetykit_client @safetykit_client ||= SafetyKit::Client.new( api_key: ENV.fetch("SAFETYKIT_API_KEY"), timeout: 2, ) end
def current_session_hash return nil if session.id.blank?
Digest::SHA256.hexdigest(session.id.to_s) endendSee the client_sessions.create_session API reference for the full Ruby method signature, request parameters, and response fields.
Send at least one of customer_user_id or customer_session_hash when creating a SafetyKit session token.
customer_user_id should be the same canonical user ID string that you send as user_id in SafetyKit server-to-server events. customer_session_hash should be a stable opaque customer-owned identifier or hash for the browser session, not a raw session value.
The session response contains:
session_token: browser-safe token used to initialize the Webapp SDK.sdk_script_url: SafetyKit-hosted browser SDK script URL to load for this page.
Create a new session for each rendered page; do not reuse session tokens across page loads.
Browser Snippet
Section titled “Browser Snippet”Render the browser snippet in your layout or template only when the server created a SafetyKit session. JSON-encode both response values when injecting them into the page, and escape < so the values cannot break out of the script tag.
The example below uses EJS; any server-side template works the same way.
<% const safetykitSession = locals.safetykitWebappSession %>
<% if (safetykitSession && safetykitSession.session_token && safetykitSession.sdk_script_url) { %> <script> (function () { var script = document.createElement("script"); script.async = true; script.src = <%- JSON.stringify(safetykitSession.sdk_script_url).replace(/</g, "\\u003c") %>;
script.addEventListener("load", function () { try { if (window.SafetyKit && typeof window.SafetyKit.init === "function") { window.SafetyKit.init({ sessionToken: <%- JSON.stringify(safetykitSession.session_token).replace(/</g, "\\u003c") %> }); } } catch (_) {} });
document.head.appendChild(script); })(); </script><% } %><% session_token = @safetykit_webapp_session&.session_token %><% sdk_script_url = @safetykit_webapp_session&.sdk_script_url %>
<% if session_token.present? && sdk_script_url.present? %> <%= javascript_tag nonce: true do %> (function() { var script = document.createElement("script"); script.async = true; script.src = <%= raw json_escape(sdk_script_url.to_json) %>;
script.addEventListener("load", function() { try { if (window.SafetyKit && typeof window.SafetyKit.init === "function") { window.SafetyKit.init({ sessionToken: <%= raw json_escape(session_token.to_json) %> }); } } catch (_) {} });
document.head.appendChild(script); })(); <% end %><% end %>If your app uses Content Security Policy, allow the origin of the returned sdk_script_url (currently https://cdn.sk-diagnostics.com) in script-src and https://ingest.sk-diagnostics.com in connect-src. If your policy uses nonces, add your per-request nonce to the inline snippet’s <script> tag, as the Rails example does with javascript_tag nonce: true.
Do not expose your SafetyKit API key in browser code. Do not hardcode the SDK script URL; load the sdk_script_url returned by the session response. If the CDN script fails to load, the page should continue normally without SafetyKit browser telemetry.
Verify the Integration
Section titled “Verify the Integration”The integration fails open, so a broken setup still renders pages normally — check the browser rather than your server logs. Load a page as a signed-in user and confirm in the browser network tab that the SDK script loads from the sdk_script_url origin and the page then sends requests to https://ingest.sk-diagnostics.com. If neither request appears, the server-side session creation is most likely failing or returning no session; log and inspect the error from the session creation call.