Initialize Pendo on window.parent or window.top with the @pendo/agent package
Situation
We have a setup where our React application runs in an iframe and we can only run code inside of the iframe.
The problem that occurs here is that when we run the initialize method from the @pendo/agent package. In that case, it will only work inside of the iframes so it won't properly run when entering into the editor (and likely also when running guides in production later on).
Known Legacy Fix
When we encountered this problem ~7 months ago, the solution provided by you (the Pendo team) was to modify existing initialisation script to always inject the pendo function into the window.parent and interact with the global Pendo object there.
The code snipped you see below works but not sure how long and keeping this up to date would be hard. The preferred way would be using the initialize method from the @pendo/agent package instead of manually copying minified code. As far as I can tell, there is no way of making that function initialize on window.parent. The 'frameIdentitySync' and 'autoFrameInstall' options documented here will only do something similar to "children" iframes, not parents.
const [isPendoLoaded, setIsPendoLoaded] = useState(false)
useEffect(() => {
if (window.pendo) {
return
}
;(function (p, e, n, d, o) {
let v, w, x, y, z
o = p[d] = p[d] || {}
o._q = []
v = ["initialize", "identify", "updateOptions", "pageLoad"]
for (w = 0, x = v.length; w < x; ++w) {
;(function (m) {
o[m] =
o[m] ||
function () {
o._q[m === v[0] ? "unshift" : "push"]([m])
}
})(v[w])
}
y = e.createElement(n)
y.async = true
y.onload = () => {
setIsPendoLoaded(true)
}
y.src = `https://cdn.eu.pendo.io/agent/static/${import.meta.env.VITE_PENDO_KEY}/pendo.js`
z = e.getElementsByTagName(n)[0]
z.parentNode.insertBefore(y, z)
})(window, document, "script", "pendo")
}, [])
useEffect(() => {
if (
!isPendoLoaded ||
!ownUser?.eMail ||
!ownUser?.firstName ||
!ownUser?.lastName
) {
return
}
if (isRunningInIFrame) {
const parentDoc = window.parent.document
const script = parentDoc.createElement("script")
script.src = `https://cdn.eu.pendo.io/agent/static/${import.meta.env.VITE_PENDO_KEY}/pendo.js`
script.async = true
script.onload = () => {
window.parent.pendo.initialize({
visitor: {
id: ownUser.eMail,
email: ownUser.eMail,
name: `${ownUser.firstName} ${ownUser.lastName}`,
},
account: {
id: "companyId",
name: "companyName",
},
})
}
parentDoc.head.appendChild(script)
}
window.pendo.initialize({
visitor: {
id: ownUser.eMail,
email: ownUser.eMail,
name: `${ownUser.firstName} ${ownUser.lastName}`,
role: "Developer",
businessPartnerKey: ownUser.businessPartnerKey,
language: ownUser.language,
},
account: {
id: "osapiens",
name: "Osapiens",
plan: "Premium",
},
})
}, [isPendoLoaded, ownUser])
Suggested Solution
The best way of solving this from my perspective would be to have an option like "initOnParentFrame" or similar that can be set in the options object and that makes pendo initialize on the parent iframe:
import { initialize } from "@pendo/agent"
initialize({
apiKey: 'example',
env: "eu",
visitor: {
id: await hashString(ownUser.eMail),
language: 'en',
},
initOnParentFrame: true,
})
Alternatively, there could be an option that lets you override the window object with window.parent or window.top:
import { initialize } from "@pendo/agent"
initialize({
apiKey: 'example',
env: "eu",
visitor: {
id: await hashString(ownUser.eMail),
language: 'en',
},
overrideWindow: window.parent
})
Comments
Please sign in to leave a comment.