Skip to main content
Version: Javascript tag

Hooks

Set hooksโ€‹

You can define custom hooks to be executed on various events.

Thanks to this you will be able to interact with your website when a survey appears, or execute some custom actions when a survey is submitted.

You can define hooks on init and survey.start commands. Hooks are all optional.

Available hooksโ€‹

Hook NameAvailable on initAvailable on survey.start
onSurveyShowedYes โœ…Yes โœ…
onMessageShowedYes โœ…Yes โœ…
onSurveyStartedYes โœ…Yes โœ…
onMessageStartedYes โœ…Yes โœ…
onQuestionRepliedYes โœ…Yes โœ…
onButtonNavigateStartedYes โœ…Yes โœ…
onButtonNavigateCompletedYes โœ…Yes โœ…
onSurveyCompletedYes โœ…Yes โœ…
onMessageCompletedYes โœ…Yes โœ…
onSurveyHiddenYes โœ…Yes โœ…
onMessageHiddenYes โœ…Yes โœ…
onAppStoreRatingTriggeredYes โœ…Yes โœ…
onReadyYes โœ…No โŒ
onSurveyDisplayAllowedYes โœ…No โŒ
onMessageDisplayAllowedYes โœ…No โŒ

onSurveyShowedโ€‹

Called when a survey is showed.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onSurveyShowed: (payload) => {
console.log("Survey has been showed", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
survey: {
id: string,
survey_position: "center-left" | "center-center" | "center-right" | "bottom-left" | "bottom-center" | "bottom-right",
survey_size: 25 | 50 | 75 | 100 | 125 | 150,
survey_format: "conversational" | "cards",
},
response: {
id: string,
items: {
question: {
id: string;
title: string;
type: "text" | "video";
url: string;
};
answer: {
fields: {
type: "string" | "number" | "boolean" | "none" | "time" | "url";
text: string;
number: number;
boolean: boolean;
time: Date;
button_url?: string;
button_url_target?: "in-page" | "in-page-spa" | "new-tab";
button_actions?: object[];
}[] | undefined;
replied_at: Date | undefined;
};
}[];
},
user: {
anonymous_id: string,
user_id: string,
}
}

onMessageShowedโ€‹

Called when a message is showed.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onMessageShowed: (payload) => {
console.log("Message has been showed", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
message: {
message_size: 25 | 50 | 75 | 100 | 125 | 150;
id: string | null;
},
response: {
id: string,
items: {
question: {
id: string;
title: string;
type: "text" | "video";
url: string;
};
answer: {
fields: {
type: "string" | "number" | "boolean" | "none" | "time" | "url";
text: string;
number: number;
boolean: boolean;
time: Date;
button_url?: string;
button_url_target?: "in-page" | "in-page-spa" | "new-tab";
button_actions?: object[];
}[] | undefined;
replied_at: Date | undefined;
};
}[];
},
user: {
anonymous_id: string,
user_id: string,
}
}

onSurveyStartedโ€‹

Called when a survey is started.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onSurveyStarted: (payload) => {
console.log("Survey has been started", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
survey: {
id: string,
survey_position: "center-left" | "center-center" | "center-right" | "bottom-left" | "bottom-center" | "bottom-right",
survey_size: 25 | 50 | 75 | 100 | 125 | 150,
survey_format: "conversational" | "cards",
},
response: {
id: string,
},
user: {
anonymous_id: string,
user_id: string,
}
}

onMessageStartedโ€‹

Called when a message is started.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onMessageStarted: (payload) => {
console.log("Message has been started", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
message: {
message_size: 25 | 50 | 75 | 100 | 125 | 150;
id: string | null;
},
response: {
id: string,
},
user: {
anonymous_id: string,
user_id: string,
}
}

onQuestionRepliedโ€‹

Called when a question is replied.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onQuestionReplied: (payload) => {
console.log("Question has been replied", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
survey: {
id: string,
survey_position: "center-left" | "center-center" | "center-right" | "bottom-left" | "bottom-center" | "bottom-right",
survey_size: 25 | 50 | 75 | 100 | 125 | 150,
survey_format: "conversational" | "cards",
},
response: {
id: string,
status: "started" | "ended" | "closed" | "interrupted"
question: {
id: string;
title: string;
type: "text" | "video";
url: string;
};
answer: {
fields: {
type: "string" | "number" | "boolean" | "none" | "time" | "url";
text: string;
number: number;
boolean: boolean;
time: Date;
button_url?: string;
button_url_target?: "in-page" | "in-page-spa" | "new-tab";
button_actions?: object[];
}[];
};
items: {
question: {
id: string;
title: string;
type: "text" | "video";
url: string;
};
answer: {
fields: {
type: "string" | "number" | "boolean" | "none" | "time" | "url";
text: string;
number: number;
boolean: boolean;
time: Date;
button_url?: string;
button_url_target?: "in-page" | "in-page-spa" | "new-tab";
button_actions?: object[];
}[] | undefined;
replied_at: Date | undefined;
};
}[];
},
user: {
anonymous_id: string,
user_id: string,
}
}

onButtonNavigateStartedโ€‹

Called right before a message/tour button's "Navigate to URL" action runs โ€” this is the button-click equivalent of navigation, for buttons that are not tied to a question reply (e.g. a message or tour CTA). For an in-page target the page is about to unload, so this may be the last hook your code gets to run.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onButtonNavigateStarted: (payload) => {
console.log("Button navigate is about to start", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
survey: {
id: string,
survey_position: "center-left" | "center-center" | "center-right" | "bottom-left" | "bottom-center" | "bottom-right",
survey_size: 25 | 50 | 75 | 100 | 125 | 150,
survey_format: "conversational" | "cards",
},
response: {
id: string,
},
button: {
url: string,
url_target: "in-page" | "in-page-spa" | "new-tab",
},
user: {
anonymous_id: string,
user_id: string,
}
}

onButtonNavigateCompletedโ€‹

Called after a message/tour button's "Navigate to URL" action has run. Not called for an in-page target, since the page reload destroys the SDK before it can run โ€” use in-page-spa (history.pushState, no reload) or new-tab if you need this hook to fire reliably.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onButtonNavigateCompleted: (payload) => {
console.log("Button navigate has completed", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
survey: {
id: string,
survey_position: "center-left" | "center-center" | "center-right" | "bottom-left" | "bottom-center" | "bottom-right",
survey_size: 25 | 50 | 75 | 100 | 125 | 150,
survey_format: "conversational" | "cards",
},
response: {
id: string,
},
button: {
url: string,
url_target: "in-page" | "in-page-spa" | "new-tab",
},
user: {
anonymous_id: string,
user_id: string,
}
}

SPA navigation with in-page-spaโ€‹

The in-page-spa target navigates without a full page reload, so the SDK and the onButtonNavigateCompleted hook survive. It auto-detects the host router across frameworks:

  • Click-interception routers (SvelteKit, Astro view transitions, Nuxt) โ€” a real anchor click is dispatched and the router navigates with its own state.
  • History-API routers (React Router, Angular, Vue history mode) โ€” falls back to history.pushState + a popstate event; hash-mode routers also get a hashchange event.

Cross-origin targets can't be an in-page navigation and always trigger a normal full navigation.

For a router that exposes neither entry point, register your own handler at init:

$screeb("init", "<website-id>", {
spaNavigationHandler: (url) => router.navigate(url), // your router's push
});

When set, spaNavigationHandler receives the fully-qualified same-origin URL and owns the in-page navigation. It may return a promise, which the SDK awaits before firing onButtonNavigateCompleted.

onSurveyCompletedโ€‹

Called when a survey is completed.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onSurveyCompleted: (payload) => {
console.log("Survey has been completed", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
survey: {
id: string,
survey_position: "center-left" | "center-center" | "center-right" | "bottom-left" | "bottom-center" | "bottom-right",
survey_size: 25 | 50 | 75 | 100 | 125 | 150,
survey_format: "conversational" | "cards",
},
response: {
id: string,
items: {
question: {
id: string;
title: string;
type: "text" | "video";
url: string;
};
answer: {
fields: {
type: "string" | "number" | "boolean" | "none" | "time" | "url";
text: string;
number: number;
boolean: boolean;
time: Date;
button_url?: string;
button_url_target?: "in-page" | "in-page-spa" | "new-tab";
button_actions?: object[];
}[] | undefined;
replied_at: Date | undefined;
};
}[];
},
user: {
anonymous_id: string,
user_id: string,
}
}

onMessageCompletedโ€‹

Called when a message is completed.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onMessageCompleted: (payload) => {
console.log("Message has been completed", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
message: {
message_size: 25 | 50 | 75 | 100 | 125 | 150;
id: string | null;
},
response: {
id: string,
items: {
question: {
id: string;
title: string;
type: "text" | "video";
url: string;
};
answer: {
fields: {
type: "string" | "number" | "boolean" | "none" | "time" | "url";
text: string;
number: number;
boolean: boolean;
time: Date;
button_url?: string;
button_url_target?: "in-page" | "in-page-spa" | "new-tab";
button_actions?: object[];
}[] | undefined;
replied_at: Date | undefined;
};
}[];
},
user: {
anonymous_id: string,
user_id: string,
}
}

onSurveyHiddenโ€‹

Called when a survey is hidden.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onSurveyHidden: (payload) => {
console.log("Survey has been hidden", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
survey: {
id: string,
survey_position: "center-left" | "center-center" | "center-right" | "bottom-left" | "bottom-center" | "bottom-right",
survey_size: 25 | 50 | 75 | 100 | 125 | 150,
survey_format: "conversational" | "cards",
},
response: {
id: string,
hide_reason: "started" | "ended" | "closed" | "interrupted",
items: {
question: {
id: string;
title: string;
type: "text" | "video";
url: string;
};
answer: {
fields: {
type: "string" | "number" | "boolean" | "none" | "time" | "url";
text: string;
number: number;
boolean: boolean;
time: Date;
button_url?: string;
button_url_target?: "in-page" | "in-page-spa" | "new-tab";
button_actions?: object[];
}[] | undefined;
replied_at: Date | undefined;
};
}[];
},
user: {
anonymous_id: string,
user_id: string,
}
}

onMessageHiddenโ€‹

Called when a message is hidden.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onMessageHidden: (payload) => {
console.log("Message has been hidden", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
message: {
message_size: 25 | 50 | 75 | 100 | 125 | 150;
id: string | null;
},
response: {
id: string,
hide_reason: "started" | "ended" | "closed" | "interrupted",
items: {
question: {
id: string;
title: string;
type: "text" | "video";
url: string;
};
answer: {
fields: {
type: "string" | "number" | "boolean" | "none" | "time" | "url";
text: string;
number: number;
boolean: boolean;
time: Date;
button_url?: string;
button_url_target?: "in-page" | "in-page-spa" | "new-tab";
button_actions?: object[];
}[] | undefined;
replied_at: Date | undefined;
};
}[];
},
user: {
anonymous_id: string,
user_id: string,
}
}

onAppStoreRatingTriggeredโ€‹

Called when an App Store Rating question is triggered.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onAppStoreRatingTriggered: (payload) => {
console.log("App Store Rating triggered", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
user: {
anonymous_id: string,
user_id: string,
}
}

onReadyโ€‹

Called when the SDK is ready. Only available on init.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onReady: (payload) => {
console.log("Screeb ready", payload);
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
user: {
anonymous_id: string,
user_id: string,
}
}

onSurveyDisplayAllowedโ€‹

Called before a survey display to allow it or not. Only available on init.

caution

The answer must arrive within 5 seconds. Past that deadline the display evaluation fails and the survey is not shown โ€” keep this callback fast and avoid slow network calls; when unsure, return true early.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onSurveyDisplayAllowed: (payload) => {
console.log("onSurveyDisplayAllowed", payload);
// return false to prevent display
return true;
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
survey: {
id: string,
},
user: {
anonymous_id: string,
user_id: string,
}
}

onMessageDisplayAllowedโ€‹

Called before a message display to allow it or not. Only available on init.

caution

The answer must arrive within 5 seconds. Past that deadline the display evaluation fails and the survey is not shown โ€” keep this callback fast and avoid slow network calls; when unsure, return true early.

Example
$screeb("init", "<website-id>", {
hooks: {
version: "1.0.0",
onMessageDisplayAllowed: (payload) => {
console.log("onMessageDisplayAllowed", payload);
// return false to prevent display
return true;
},
},
});
Payload definition
{
channel: {
id: string,
type: "widget"
},
message: {
id: string,
},
user: {
anonymous_id: string,
user_id: string,
}
}