title: How to track pageviews in RemixJS?
body: <p>I am building a Remix app, and wanted to record some user analytics in my database based on what page the user was viewing. I also wanted to do so on a route by route basis, rather than just simply the raw URL.</p>
  <p>For example: I wanted to know &quot;user viewed URL /emails/123&quot; as well as &quot;user viewed route /emails/$emailId&quot;</p>
  <p>This problem could be generalized as &quot;I want to run a piece of server code once per user navigation&quot;</p>
  <p>For my tracking I'm assuming users have javascript enabled in their browser.</p>
  <h1>Solutions I tried:</h1>
  <h2>Record in the loader</h2>
  <p>This would be something like:</p>
  <pre><code>export const loader: LoaderFunction = async ({ request, params }): Promise&lt;LoaderData&gt; =&gt; {
    myDb.recordPageVisit(request.url);
  }
  </code></pre>
  <p>This doesn't work because the loader can be called multiple times per page visit (eg. after an action is run)</p>
  <p>It's possible that there's some value hidden in the request parameter that tells us whether this is an initial page load or if it's a later visit, but if so I couldn't find it, including when I examined the raw HTTP requests.</p>
  <p>It's also annoying to have to put this code inside of every loader.</p>
  <h2>Record the URL in the node code</h2>
  <p>I'm using @remix-run/node as my base remix server, so I have the escape hatch of setting up node middleware, and I thought that might be a good answer:</p>
  <pre><code>  const app = express();
    app.use((req, res, next) =&gt; {
      if (req.url.indexOf(&quot;_data&quot;) == -1) {
        myDb.recordPageVisit(req.url);
      }
      next();
    });
  </code></pre>
  <p>I tried ignoring routes with <code>_data</code> in them, but that didn't work because remix is being efficient and when the user navigates, it is using an ajax-y call to only get the loaderData rather than getting the full rendered page from the server. I know this is the behavior of Remix, but I had not remembered it before I went down this path :facepalm:</p>
  <p>As far as I can tell it's impossible to stateless-ly track unique pageviews (ie based purely on the current URL) - you need see the user's previous page as well.</p>
  <p>I wondered if referer would allow this to work statelessly, but it appears that the referer is not behaving how I'd hoped: the referer header is already set to the current page in the first loader request for the data for the page. So initial load and load-after-mutation appear identical based on referer. I don't know if this is technically a bug, but it's certainly not the behavior I'd expect.</p>