This guide covers how to add the Persona Sentinel iframe to your webpage.
Setup
Ask your Persona Account team to set up a Sentinel transaction type and a client token before you start. You need both values to build the collection URL below.
Instructions
-
Load the Sentinel collection URL.
Embed a link to the Sentinel collection endpoint, with your client token and transaction type ID substituted as shown below.
https://withpersona.com/sentinel?client-token={{CLIENT_TOKEN}}&transaction-type-id={{TXN_TYPE_ID}}&context={{CONTEXT}}&account-reference-id={{REFERENCE_ID}}&auto-create-account=true&auto-create-account-type-id={{ACCOUNT_TYPE_ID}}Here’s an overview of parameters. Note that two are optional:
Parameter Description contextRequired. A string that represents any contextual enrichment you’d like to provide for the event, such as onboardingEvent.account-reference-idRequired. A string parameter for including the user’s reference ID. Using this parameter ensures that information from the Sentinel event is synced to Graph, if you use it. auto-create-accountOptional. A boolean string ( trueorfalse) that controls whether an account is auto-created when one does not already exist for the givenaccount-reference-id. Set tofalseto opt out of auto-creation; any other value is treated astrue.auto-create-account-type-idOptional. An account type token (prefix acttp_) that specifies the account type to use when auto-creating an account. If omitted, defaults to the transaction type’s configured default account type.To verify this is working, visit the URL above. This should result in three network calls:
- two calls to
fp-us.withpersona.comfor browser and device fingerprinting - one call to
withpersona.com/api/sentinel/v1/transactionsto create the Transaction
A blank page should load. Inspect the page and check the Network tab to verify.
- two calls to
-
Create the Transaction.
To trigger Transaction creation, which sends the device information, context, and identifiers to Persona, post a message to the content window containing the
sentinelpage.If the page was opened directly in the main window, open the console and use:
window.postMessage({ type: 'persona/passive/collect', origin: 'https://withpersona.com' })If the page is embedded within an iframe, use:
document .getElementById('{{MY_IFRAME_ID}}') .contentWindow.postMessage( { type: 'persona/passive/collect', origin: '{{MY_ORIGIN}}' }, 'https://withpersona.com' )
Recommended usage and sample implementation
Embed the Sentinel URL in an iframe, and only load the iframe and send the Transaction as needed.
import React, { useState, useRef, useMemo, useEffect } from 'https://esm.sh/react@18'
import ReactDOM from 'https://esm.sh/react-dom@18'
function SentinelContainer() {
const [iframeLoaded, setIframeLoaded] = useState(false)
const [sentinelCollecting, setSentinelCollecting] = useState(false)
// To store the callback result from Sentinel
const [postResult, setPostResult] = useState(null)
const iframeRef = useRef(null)
const buttonRef = useRef(null)
const memoizedIframe = useMemo(
() => (
<iframe
style={{ display: 'none' }}
ref={iframeRef}
id="sentinel"
src="https://withpersona.com/sentinel?client-token={CLIENT_TOKEN}&transaction-type-id={TXN_TYPE_ID}&context=referenceImplementation&account-reference-id={REFERENCE_ID}"
/>
),
[]
)
const handleIframeLoad = () => {
setIframeLoaded(true)
}
const handleMessage = (message) => {
if (message.origin === 'https://withpersona.com') {
setPostResult(message.data)
setSentinelCollecting(false)
}
}
useEffect(() => {
// Add a message event listener to your application to handle postMessage callbacks
window.addEventListener('message', handleMessage)
const iframeElement = iframeRef.current
if (iframeElement) {
// Add a load event listener to the iframe to detect when it has finished loading
iframeElement.addEventListener('load', handleIframeLoad)
}
// Return value is used to provide a cleanup function for React's useEffect
return () => {
window.removeEventListener('message', handleMessage)
if (iframeElement) {
iframeElement.removeEventListener('load', handleIframeLoad)
}
}
}, [])
const handleClick = () => {
if (iframeRef.current && iframeRef.current.contentWindow) {
setSentinelCollecting(true)
// Post a message to the Sentinel iframe to begin collection
iframeRef.current.contentWindow.postMessage(
// The origin refers to the domain in which the iframe is being embedded
{ type: 'persona/passive/collect', origin: 'https://mywebpage.com' },
// The second parameter is the target origin, this should be https://withpersona.com
// (or the domain matching the Sentinel endpoint being used for the iframe)
'https://withpersona.com/'
)
}
}
useEffect(() => {
// Add a click event listener to the button that starts collection
const buttonElement = buttonRef.current
if (buttonElement) buttonElement.addEventListener('click', handleClick)
return () => {
if (buttonElement) buttonElement.removeEventListener('click', handleClick)
}
}, [])
return (
<>
{memoizedIframe}
<h1>Hello World</h1>
<p>Iframe loaded: {iframeLoaded.toString()}</p>
<p>Sentinel result: {sentinelCollecting ? 'Loading...' : ''}</p>
<pre>{postResult ? JSON.stringify(postResult, null, 2) : 'No data available'}</pre>
<button ref={buttonRef} disabled={!iframeLoaded || sentinelCollecting}>
Click Me
</button>
</>
)
}
// Tells React to attach the SentinelContainer component to the 'root' HTML div
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<SentinelContainer />)
Other parameters
Routing country
For end users and customers on the DE shard, taking advantage of geographical routing may be desired to reduce client-facing latencies. Since the /sentinel endpoint is fetched via a GET request when loaded via an iframe, you can specify an additional query string parameter:
https://withpersona.com/sentinel?client-token={{CLIENT_TOKEN}}&transaction-type-id={{TXN_TYPE_ID}}&routing-country=US
You can specify either US or DE for the routing-country query string parameter. Subsequent API calls made to Persona are routed accordingly.
This parameter primarily affects the Create Transaction API call. The initial /sentinel page load may still be served from a US-based server.