Member.uuid for use in code injection

What is the proper way to access member.uuid in the code injection (not on the server)?

For example Ghost’s Intercom integration docs are using only the basic snippet allowing anyone to start a chat. Limiting access to an Intercom chat only to members seems a more valid use case (AI chats at Intercom cost $1/chat which could be a costly). I added the chat only on a single page and set “Page access” to “Members only”.

However I still need to send member.uuid to Intercom:

window.intercomSettings = {
  api_base: "https://api-iam.intercom.io",
  app_id: "12345678",
  user_id: member.uuid,
  name: member.name,
  email: member.email,
  //created_at: user.createdAt,
};

The member JSON is retrieved by Ghost and is available to the React app. Can it be made available as a global object?

The only workaround I could write is an unstable hack:

<script>
  window.addEventListener('load', (event) => {
    var e = document.getElementById('ghost-portal-root');
    const checkInitialization = () => {
      var s = e._reactRootContainer._internalRoot.current.child.child.memoizedState;
      var member = s.member;
      if (member) {
		window.intercomSettings = {
		  api_base: "https://api-iam.intercom.io",
		  app_id: "12345678",
		  user_id: member.uuid,
		  name: member.name,
		  email: member.email,
		  //created_at: user.createdAt,
		};
		
		// We pre-filled your app ID in the widget URL: 'https://widget.intercom.io/widget/app_id'
        (function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/12345678';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();

      } else if (s.page == '') {
        // Stop checking.
        //console.error('Member element not found');
      } else {
        // Check again after a short delay
        setTimeout(checkInitialization, 100);
      }
    };

    // Start checking for initialization
    checkInitialization();
  });
</script>

I’ll appreciate any guidance on how to write a proper code injection :blush:

Can you edit the theme? If so, drop this somewhere above where you need the uuid available:

{{#if @member}}
  <script>
      set memberUUID = "{{@member.uuid}}"
</script>
{{/if}}

Then your later script will have access to that value.

1 Like

Thank you for the suggestion Cathy. However I would like to avoid editing the theme.

It would be great if there was a “code injection” for the server side available in the Ghost settings. This way we could “code inject” the code you provided to any theme/site :thinking:

Ghost is secure and fast because it doesn’t allow arbitrary code injection to run server side. But… I think it might be reasonable to set a js variable with member data like this. Maybe drop it over in the Ideas forum?

1 Like