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 Name | Available on init | Available on survey.start |
|---|---|---|
onSurveyShowed | Yes โ | Yes โ |
onMessageShowed | Yes โ | Yes โ |
onSurveyStarted | Yes โ | Yes โ |
onMessageStarted | Yes โ | Yes โ |
onQuestionReplied | Yes โ | Yes โ |
onButtonNavigateStarted | Yes โ | Yes โ |
onButtonNavigateCompleted | Yes โ | Yes โ |
onSurveyCompleted | Yes โ | Yes โ |
onMessageCompleted | Yes โ | Yes โ |
onSurveyHidden | Yes โ | Yes โ |
onMessageHidden | Yes โ | Yes โ |
onAppStoreRatingTriggered | Yes โ | Yes โ |
onReady | Yes โ | No โ |
onSurveyDisplayAllowed | Yes โ | No โ |
onMessageDisplayAllowed | Yes โ | 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+ apopstateevent; hash-mode routers also get ahashchangeevent.
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.
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.
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,
}
}