javascriptreactjsgatsbyreact-helmet

Gatsby 3rd party scripts not working as intended


I have the problem with including fastspring to my gatsby project. Problem is the following: I add the script in html head but it doesn't work on all pages(it works only if I refresh the page) I tried to fix that by inserting script in html.js, with gatsby-ssr.js and gatsby-browser.js

gatsby-browser.js enter image description here

I put the same code in gatsby-ssr.js, I have also tried with Helmet but nothing works for me I want it to work on all the pages without needing to refresh the page, so if somebody could help me with this. Thanks in advance! :)


Solution

  • Seems like an old issue, but someone might still have the problem. I did search for a solution to it for some time and in the end, I went with the following.

    1. I created a component called FastSpringStoreApi.js. It loads FastSpring API and subscribes to 2 callback events from it - data-popup-closed and data-data-callback. I used this two to dispatch custom js events for which I listen in my FastSpring provider. These 2 events contain all information needed for store to function (items, pricing, cart information)

    Note: there is a reason I save data into sessionStorage. The event can be dispatched before React hydrates. And in cases like this I take data in session storage as initial state in my reducers.

    import React from 'react';
    import {
      FS_EVENTS,
      FS_SESSION_KEY
    } from './FastSpringStore.keys';
    
    export default ({ storeFrontId }) => (
      <>
        <script
          type="text/javascript"
          dangerouslySetInnerHTML= {{
            __html:`
              function raiseFSPopupCloseEvent(data) {
                var popupCloseEvent = new CustomEvent(
                 '${FS_EVENTS.POPUP_CLOSE}',
                 { detail: data }
                );
                window.dispatchEvent(popupCloseEvent);
              }
              
              function raiseFSDataUpdateEvent(data) {
                var dataUpdateEvent = new CustomEvent(
                 '${FS_EVENTS.DATA_UPDATE}',
                 { detail: data }
                );
                
                window
                  .sessionStorage
                  .setItem(
                    '${FS_SESSION_KEY}',
                     JSON.stringify(data)
                   )
                  
                window.dispatchEvent(dataUpdateEvent);
              }
            `
          }}
        />
        <script
          id="fsc-api"
          src="https://d1f8f9xcsvx3ha.cloudfront.net/sbl/0.8.5/fastspring-builder.min.js"
          type="text/javascript"
          data-popup-closed="raiseFSPopupCloseEvent"
          data-data-callback="raiseFSDataUpdateEvent"
          data-continuous="true"
          data-storefront={storeFrontId}
        />
      </>
    )
    
    1. I load this component inside gatsby-ssr.js only
    export const onRenderBody = ({ setHeadComponents }) => {
      setHeadComponents([
        <FastSpringStoreApi
          key="fast-spring-store-api"
          storeFrontId="..."
        />,
      ])
    }
    
    1. I have FasSpringStore provider where I subscribe to my fs events. Looks like this. With it I can get all data needed further down to any of the components.
    useEffect(() => {
        const onPopupClosed = (data) => {
          // Popup was closed and order was finished (we have order id)
          if (_has(data.detail, 'id')) {
            // Navigate to home page
            // TODO: Show thank you page in the future
            navigate('/')
            dispatch(cleanShopStore())
          }
        }
    
        const onDataUpdate = (data) => {
          dispatch(
            setOrderInfo(
              mapFSDataToPayload(
                data.detail
              )
            )
          )
        }
    
        window.addEventListener(FS_EVENTS.POPUP_CLOSE, onPopupClosed, false);
        window.addEventListener(FS_EVENTS.DATA_UPDATE, onDataUpdate, false);
    
    
        return () => {
          window.removeEventListener(FS_EVENTS.POPUP_CLOSE, onPopupClosed)
          window.removeEventListener(FS_EVENTS.DATA_UPDATE, onDataUpdate)
          window.sessionStorage.removeItem(FS_SESSION_KEY)
        }
      }, [])
    
    1. Inside gatsby-ssr.js I wrap my root element with store provider
    export const wrapRootElement = ({ element }) => (
      <FastSpringStoreProvider>
        {element}
      </FastSpringStoreProvider>
    );
    
    1. Same goes for gatsby-browser.js
    export const wrapRootElement = ({ element }) => (
      <FastSpringStoreProvider>
        {element}
      </FastSpringStoreProvider>
    );
    

    Hope this gives some ideas for FastSpring implementation.