Skip to content
This repository has been archived by the owner on Apr 28, 2022. It is now read-only.

Support and documentation for Server Side Rendering and Static Site Generation #648

Open
bscaspar opened this issue Oct 22, 2020 · 1 comment

Comments

@bscaspar
Copy link

SSR and SSG are increasingly popular web technologies, having well documented support for integrating Segment with these type of rendering would improve Segment's DX among many new projects, teams, and startups.

I use Next.js and had to do some searching along with trial and error to connect analytics.js to my app. Next does not use any static html files when developing - it pre-renders them at build/run time from jsx or tsx files. When the static pages are pre-rendered on the server (at build time/request time) the window variable doesn't exist, so the <script> snippet throws an error.

Generally, I would prefer to have control over the delivery of any javascript libraries, and I see similar sentiment across the issues for analytics.js and analytics.js-core.

Here's a workaround I found (so far) to be successful for adding the appropriate script tag in case anyone else is searching for this as I was. One note on the snippet itself - I wrote it inline at first to increase the readability and Typescript threw a number of errors, so you'll see a few tweaks and ts-ignore statements (even though it's in a template literal and TS doesn't parse it anymore).

/* _app.tsx */
  useEffect(() => {
     // add Segment
    const scriptEl = document.createElement('script');
    const scriptText = document.createTextNode(
      ` !(function () {
              // @ts-ignore
              const analytics = (window.analytics = window?.analytics || []);
              if (!analytics.initialize)
                if (analytics.invoked) {
                  window.console &&
                    console.error &&
                    console.error('Segment snippet included twice.');
                } else {
                  analytics.invoked = !0;
                  analytics.methods = [
                    'trackSubmit',
                    'trackClick',
                    'trackLink',
                    'trackForm',
                    'pageview',
                    'identify',
                    'reset',
                    'group',
                    'track',
                    'ready',
                    'alias',
                    'debug',
                    'page',
                    'once',
                    'off',
                    'on',
                    'addSourceMiddleware',
                    'addIntegrationMiddleware',
                    'setAnonymousId',
                    'addDestinationMiddleware',
                  ];
                  analytics.factory = function (e) {
                    return function () {
                      // eslint-disable-next-line prefer-rest-params
                      const t = Array.prototype.slice.call(arguments);
                      t.unshift(e);
                      analytics.push(t);
                      return analytics;
                    };
                  };
                  for (let e = 0; e < analytics.methods.length; e++) {
                    const key = analytics.methods[e];
                    analytics[key] = analytics.factory(key);
                  }
                  analytics.load = function (key, e) {
                    const t = document.createElement('script');
                    t.type = 'text/javascript';
                    t.async = !0;
                    t.src = 'https://cdn.segment.com/analytics.js/v1/' + key + '/analytics.min.js';
                    const n = document.getElementsByTagName('script')[0];
                    n.parentNode.insertBefore(t, n);
                    analytics._loadOptions = e;
                  };
                  analytics.SNIPPET_VERSION = '4.13.1';
                  analytics.load('${process.env.NEXT_PUBLIC_SEGMENTKEY}');
                  analytics.page();
                }
            })()`,
    );
    scriptEl.appendChild(scriptText);
    document.head.appendChild(scriptEl);
  }, []);
@bscaspar
Copy link
Author

Update: The Next.js team provides an example of integrating Segment over in their repo.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant