Developers

Last Updated: September 1st 2021

Tracking Code

We recommend that you install the tracking code within the <head> of your page so that it captures as much of the session as possible. Loading the script just before the <body/> could result in the first second or so of a visitors' session being missed.

The script is very light and loading is non-blocking, so performance should not be a concern.

You can find the correct script with your site id on the settings page of your site. Every site site is different, but here are some suggestions for where best to place the script into your app.

app/views/layouts/application.html.erb

<!DOCTYPE html>
  <html>
  <head>
    ...

    <script>
      (function(s,q,e,a,u,k,y){
        s._sqSettings={site_id:'your-site-id'};
        u=q.getElementsByTagName('head')[0];
        k=q.createElement('script');
        k.src=e+s._sqSettings.site_id;
        u.appendChild(k);
      })(window,document,'https://cdn.squeaky.ai/g/0.4.0/script.js?');
    </script>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

pages/_document.tsx

import NextDocument, { 
  Html, 
  Head, 
  Main, 
  NextScript, 
  DocumentContext,
} from 'next/document';

class Document extends NextDocument {
  static async getInitialProps(ctx: DocumentContext) {
    return NextDocument.getInitialProps(ctx);
  }

  public render(): JSX.Element {
    return (
      <Html>
        <Head>
          <script dangerouslySetInnerHTML={{ __html: `
            (function(s,q,e,a,u,k,y){
              s._sqSettings={site_id:'your-site-id'};
              u=q.getElementsByTagName('head')[0];
              k=q.createElement('script');
              k.src=e+s._sqSettings.site_id;
              u.appendChild(k);
            })(window,document,'https://cdn.squeaky.ai/g/0.4.0/script.js?');
          `}} />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      );
    }
  }
}

export default Document;

User Privacy

At Squeaky we care a lot about user privacy. We do not store any Personally Identifiable Information (PII) related to visitors or their recordings, such as their location or IP address. We try our best to make the recordings as free from PII as possible by masking all form data and any non essential meta data.

PII comes in all shapes and sizes and as a result, some responsibility will fall on the site owner.

Squeaky offers two css class names that can be used to protect your users' privacy:

.squeaky-hide will remove everything contained within it, and replace it with an element of the same dimenstions so that it does not effect the rendering of the page. You may want to use this if there is a large section of text, or some PII that is not in text form (such as an image).

It could look like the following:

<div class="squeaky-hide">
  <p>Name: Bob</p>
  <p>Email: bob@squeaky.ai</p>
  <img src="/images/profile-image.png">
</div>

.squeaky-mask will replace all text contained with asterisks. This is more suited to small pieces of text, such as a users' name appearing within a section of non identifiable text.

A common sitation may be:

<p>Welcome back, <span class="squeaky-mask">Bob</span></p>

User Identification

Privacy is important, however there are times that you may want to link some attributes to a Squeaky visitor. By default, a visitor is completely anonymous, although the site owner can associate any attributes they want with a visitor.

This is achieved by using the squeaky.identify() method that is exposed by the Squeaky script. The identify method accepts any key/values, but keys named email or name will have the added benefit of being indexed for search on the visitors page.

The identify method takes two arguments. The first is your users unique id (likely the id generated by your database), followed by a javascript object containing the key/value pairs you'd like to associate:

squeaky.identify('<your-users-uniqueid>', {
  foo: 'bar',
  bar: 'baz',
  ...
});

Once again, every site is different and the location of this is best left to you. You only need to identify a user once per session, so it can be hoisted up fairly high. Here is a recommendation:

app/views/layouts/application.html.erb

...

<body>
  <%= yield %>

  <% if user_signed_in? %>
    <script type="text/javascript">
      window.addEventListener('load', () => {
        squeaky.identify('<%= current_user.id %>', {
          name: '<%= current_user.full_name %>',
          email: '<%= current_user.email %>'
        });
      });
    </script>
  <% end %>
</body>

pages/_app.tsx

import React, { FC } from 'react';
import type { AppProps } from 'next/app';

const App: FC<AppProps> = ({ Component, pageProps }) => {
  React.useEffect(() => {
    // This assumes you are fetching the logged in user server side
    const { user } = pageProps;

    if (!user) return;

    window.addEventListener('load', () => {
      squeaky.identify(user.id, {
        name: user.fullName,
        email: user.email,
      });
    });
  }, []);

  return <Component {...pageProps} />;
};

The Squeaky script initializes and loads asynchronously, and depending on how lightweight your page is, may not be loaded by the time you try to identify the user. It is best to wait for the page to finish entirely before attempting to identify a user.