Get page views from Firebase Analytics in a Gatsby site

ReactJS|OCTOBER 4, 2024|106 VIEWS
To get page views from Firebase Analytics in a Gatsby site, you need to set up Firebase Analytics to log page views and then retrieve the analytics data from Firebase.

Hello, I’m currently using Firebase Analytics on my blog and would like to display page views for each individual post. While researching online today, I found that the information I encountered was outdated. With Google transitioning from Universal Analytics to GA4, I’m looking for a new approach to achieve my goal.

Here’s a step-by-step guide on how to set up Firebase Analytics to log page views and how you can retrieve this data using the Google Analytics Data API Client:

Step 1: Set Up Firebase Analytics to Log Page Views

Follow instruction in Setting up Firebase Analytics in a GatsbyJS application to initialize Firebase Analytics in your site

Next, now you need to log page view each time user visit your post page

Add the following lines to your blog post page:

React.useEffect(() => {
  if (typeof window !== "undefined" && firebase.analytics) {
    firebase
      .analytics()
      .logEvent("page_view", { page_path: data.mdx.fields.slug });
  }
}, []);

Sample from my blog

import * as React from "react";
import { HeadFC, graphql } from "gatsby";
import firebase from "gatsby-plugin-firebase";
const BlogPost = ({ data, children }: any) => {
  React.useEffect(() => {
    if (typeof window !== "undefined" && firebase.analytics) {
      firebase
        .analytics()
        .logEvent("page_view", { page_path: data.mdx.fields.slug });
    }
  }, []);

  return (
    <main>
      <div className="mx-auto max-w-screen-xl flex flex-col">
        <div className="p-4">
          <h1 className="text-2xl font-bold mb-4 mt-4">
            {data.mdx.frontmatter.title}
          </h1>
          <div className="mt-4 [&>p]:mb-4 [&>pre]:mb-4 post">{children}</div>
        </div>
      </div>
      <Footer />
    </main>
  );
};

export const query = graphql`
  query ($id: String) {
    mdx(id: { eq: $id }) {
      id
      frontmatter {
        title
        subtitle
        date(formatString: "MMMM D, YYYY")
      }
      fields {
        slug
      }
    }
  }
`;

export default BlogPost;

Step 2: Retrieve Analytics Data Using Google Analytics Data API Client

The process is similar to the Universal Analytics Reporting API but with some differences in the API endpoints and request structure.

1. Install Google Analytics Data API Client and Crypto:

npm install @google-analytics/data crypto

2. Create a Service Account:

Go to the Firebase Console.

Choose your project

Navigate to Project Settings and then to Service Accounts.

Create a new service account and download the JSON key file.

3. Enable Google Analytics Data API

Head over to Google Console and enable Google Analytics Data API service

Google Analytics Data API

4. Fetch Analytics Data in gatsby-node.js:

Use the @google-analytics/data package to fetch analytics data in your gatsby-node.js file.

Example code in gatsby-node.js:

const crypto = require("crypto");
const { BetaAnalyticsDataClient } = require("@google-analytics/data");

const analyticsDataClient = new BetaAnalyticsDataClient({
  credentials: {
    client_email: YOUR_CLIENT_EMAIL,
    private_key: YOUR_PRIVATE_KEY,
  },
});

exports.sourceNodes = async ({ actions }) => {
  const { createNode } = actions;

  const [response] = await analyticsDataClient.runReport({
    property: "properties/YOUR_PROPERTY_ID",
    dateRanges: [
      {
        startDate: "30daysAgo",
        endDate: "today",
      },
    ],
    dimensions: [
      {
        name: "pagePath",
      },
    ],
    metrics: [
      {
        name: "screenPageViews",
      },
    ],
    orderBys: [
      {
        desc: true,
        metric: {
          metricName: "screenPageViews",
        },
      },
    ],
  });

  // Process the response data.
  let rows = response.rows;
  rows = rows.map((row) => {
    const path = row.dimensionValues[0].value;
    const totalCount = row.metricValues[0].value;
    return {
      path,
      totalCount,
    };
  });

  // Add analytics data to graphql
  for (const { path, totalCount } of rows) {
    createNode({
      path,
      totalCount: Number(totalCount),
      id: path,
      internal: {
        type: `PageViews`,
        contentDigest: crypto
          .createHash(`md5`)
          .update(JSON.stringify({ path, totalCount }))
          .digest(`hex`),
        mediaType: `text/plain`,
        description: `Page views per path`,
      },
    });
  }
};

YOUR_CLIENT_EMAIL and YOUR_PRIVATE_KEY you can read from service account JSON key file

5. How can you get YOUR_PROPERTY_ID?

Go to the Google Analytics dashboard.

Select the desired account and property

Click on the Admin gear icon located in the bottom left corner.

Navigate to Property Settings, then to Property, and finally Property Details.

You will find YOUR_PROPERTY_ID in the top right corner.

6. Next, Ensure the Service Account Has Access

Click on Property access management

Add the service account email (found in your service account JSON key file under client_email) with Viewer or Editor permissions.

7. Run a test

Note that contentDigest should be unique because it is used for caching

Now run npm start and check localhost:8000__graphql there should be two new fields to query, pageViews and allPageViews. The first takes an id (slug) as parameter, the second displays all pages.

Example allPageViews query

allPageViews query

Step 3: Displaying the new data

Now that we can get our page views from graphql

import * as React from "react";
import { HeadFC, graphql } from "gatsby";
import firebase from "gatsby-plugin-firebase";

const BlogPost = ({ data, children }: any) => {
  React.useEffect(() => {
    if (typeof window !== "undefined" && firebase.analytics) {
      firebase
        .analytics()
        .logEvent("page_view", { page_path: data.mdx.fields.slug });
    }
  }, []);

  const pageView = data.allPageViews.nodes.find(
    (p: any) => p.path === data.mdx.fields.slug
  );

  return (
    <main>
      <div className="mx-auto max-w-screen-xl flex flex-col">
        <div className="p-4">
          <h1 className="text-2xl font-bold mb-4 mt-4">
            {data.mdx.frontmatter.title}
          </h1>
          <div className="flex text-sm gap-3 items-center text-gray-500">
            <span>{pageView?.totalCount ?? 0} VIEWS</span>
          </div>
          <div className="mt-4 [&>p]:mb-4 [&>pre]:mb-4 post">{children}</div>
        </div>
      </div>
    </main>
  );
};

export const query = graphql`
  query ($id: String) {
    mdx(id: { eq: $id }) {
      id
      frontmatter {
        title
        subtitle
        date(formatString: "MMMM D, YYYY")
      }
      fields {
        slug
      }
    }
    allPageViews {
      nodes {
        path
        totalCount
      }
    }
  }
`;

export default BlogPost;

That's it