brazeBridge and appboyBridge names, so most Braze custom HTML runs
unchanged.
Create one
- Add a Show In-App step to a sequence and pick HTML as the format.
- Paste your document, or click Upload .html. It can be up to 100 KB; load images, fonts and scripts from https URLs instead of inlining large files.
- Give it a Title. Screen readers announce it, and it names the message in the contact’s history. It is not drawn on screen.
- Leave Close button on unless your HTML always shows its own close
control (
sequenzy.close(),brazeBridge.closeMessage()or an element withdata-sequenzy-close). Sequenzy turns it off for you when you upload or paste a document that has one.
<p>Hi {{firstName|there}}</p>. Two extra tags exist for HTML messages:
{{contactId}} (the Sequenzy contact ID) and {{externalId}} (your own user
ID). Each value is escaped for where it lands: as HTML in text and
attributes, and as JavaScript string text inside <script> and on...
attributes, so put tags in scripts inside quotes:
var name = "{{firstName}}";. A contact’s own data, such as a name typed
into a form, can’t change your document’s markup or code.
You can also create HTML steps through the API (format: "html" with html
on an in_app step), the CLI (sequenzy in-app html set) and MCP
(insert_sequence_step or update_sequence_node). See
CLI and MCP.
Which apps show them
Apps on older SDK versions, and apps that fetch the feed themselves, never
receive HTML messages unless they ask for them with
formats: ["modal", "banner", "fullscreen", "html"]. The message waits in the
feed until a supported app shows it or it expires, so an older app version
never shows a blank message in its place.
A message acts only for the contact it was fetched for. When your app calls
reset or identifies someone else, every SDK removes the previous contact’s
message without reporting it, and ignores any bridge call it still sends.
The JavaScript bridge
Sequenzy adds the bridge to the top of your document before any of your own scripts run. Call it from your scripts or fromonclick attributes.
Links (
<a href>) open through the app as clicks, so deep links work and the
click is counted. Add data-sequenzy-ignore to a link to keep it inside the
message. Any element with a data-sequenzy-close attribute closes the
message when clicked, with no script needed, so it also works on websites
whose Content Security Policy blocks onclick. The Escape key and Android’s
back button close the message.
The bridge fires sequenzy:ready (and Braze’s ab.BridgeReady) on window
once the document has loaded.
Every call acts on the contact who is signed in to the app. A message cannot
change who the contact is, read other contacts, or reach your app’s own
storage. Each message can make up to 50 bridge calls each time it is shown,
and each call is limited to 32 KB. Events and attributes follow the same rules
as the SDKs’ track and setProfile: event names start with a letter or
number and are up to 100 characters, properties are up to 8 KB, and a contact
can get up to 60 event batches and 30 attribute updates a minute. Calls the
server rejects are logged in the console on the web.
Braze compatibility
changeUser, setEmail, setPhoneNumber, subscription groups, array and
increment attributes, logPurchase and requestPushPermission do nothing and
log a warning in the console: a message can’t change identity or ask for push
permission.
Braze Liquid personalization is converted to Sequenzy merge tags when you
save:
Liquid without an equivalent, such as
{% if %} blocks, Connected Content or
{{${country}}}, has to be replaced before you can save; the editor names
each one.
Survicate surveys
Survicate’s Braze In-App Message survey works as is:- In Survicate, create the survey with the Braze In-App Message type and copy the code from its Launch tab.
- Paste it into an HTML in-app step. Sequenzy converts
{{${braze_id}}}and{{${email_address}}}, which Survicate needs to show the survey. - Survicate’s script closes the message when the survey is finished or closed. Keep the close button on: if an ad blocker stops Survicate’s script, it is the way out.
survicate_question_answered event (with
surveyId, questionId, answerType and answer) and each finished survey
as survicate_survey_completed, so you can segment on answers and start
sequences from them. It uses Survicate’s JavaScript event listeners, which
need a Survicate plan with JavaScript targeting.
On the web, Survicate’s survey floats in the corner and the rest of your page
stays usable.
On the web
Adddata-sequenzy-in-app to the browser SDK snippet. It loads a separate
3 KB (gzipped) script, sequenzy-in-app.js, only on sites that use it:
sequenzy.identify(email, identityToken). The SDK checks the feed on page
load, after identify, when the tab becomes visible, and every minute. After
sequenzy.reset() or an identify for someone else, a message on screen for
the previous contact is removed.
With the npm package:
iframe with srcdoc, which
uses your page’s Content Security Policy. If your site sets one, allow
https://api.sequenzy.com in script-src and connect-src, and allow the
hosts your message loads from (the editor lists them). For Survicate that is
https://*.survicate.com and https://*.survicate-cdn.com in script-src,
style-src, font-src, img-src and connect-src. If your policy uses a
nonce, add it to the snippet’s <script> tag; the SDK copies it onto the
sequenzy-in-app.js tag and the message’s inline scripts and styles. A
message whose script your policy blocks is skipped (with a console warning)
instead of covering the page.
Security
- Web: the message runs in an
iframesandboxed withoutallow-same-origin, so it has an opaque origin of its own (servers it calls seeOrigin: null). It can run scripts, submit forms and open new tabs, but it cannot read your page, its cookies, local storage or IndexedDB, and it cannot navigate your page. It gets its own in-memory storage. - iOS: a
WKWebViewwith a private, non-persistent data store, so the message shares no cookies, storage or cache with your app’s other web views. - Android: a
WebViewwith file and content access, mixed content and third-party cookies off. - React Native:
react-native-webviewin incognito mode with shared and third-party cookies off. - Mobile: the document loads at
https://in-app.sequenzy.com, never your app’s origin. Each time it is shown, its local storage, session storage and cookies are cleared before your scripts run, so a survey’s saved state doesn’t carry over from one contact to the next on a shared device. iOS and React Native also use a private web view store. - Everywhere: navigation away from the document opens through your app’s
URL handler, which only accepts https links and app deep links;
javascript:,data:,file:and plainhttp:links are blocked. - A message that does not finish loading within 10 seconds is not shown, is not counted as displayed, and stays in the feed for a later visit. Until it has loaded it does not block taps on your app.
Limits
A step is skipped for a contact (
in_app.skipped with reason
html_too_large) when merge tags make their copy larger than 128 KB.
Results
HTML messages count like other in-app messages: created, displayed, clicked and dismissed per step. A click logged with a button ID (logClick("submit"))
records the ID on the contact’s in_app.clicked activity.
CLI and MCP
The API equivalent of the check is
Validate In-App HTML.