I originally titled this article "Migrating to Amplify" first because that was my plan because I was familiar with it, but why not try something new, and currently GCP is the cloud provider used in my day job. The other somewhat helpful thing is that it seems a bit easier to keep hosting on Netlify but wireup Firebase. So I also had to change the post name to "Adding Firebase" since it's not really a migration anymore. I guess all the features and comparisons really remain to be seen, but this is the initial stages.

I don't have a lot of experience with Google Cloud, and only some Firebase experience on the Android side (but that was many years ago). So first things first, make an account at Firebase and create a new project.

Add a new app to the project
Add a new app to the project

I called mine "The Lamp Post" because I'm unoriginal and since the next step is to click "Add app" in the project overview, and then it says to enter the app name, so I was forced into the corner I'd feared...and I called the app "website" 🙄. Then it'll spit out all the things you need to paste into your app and tell you to run npm install firebase. Honestly, it's all pretty straightforward, and since I have my app up and running I just dropped the code into my main layout.tsx and 💥.

Yup...yup, hold your horses...this is a static site with SSR optimizations so you can't just load analytics in a server side rendered layout component, and it knows it, and it wasn't happy about it. So I fired up ye olde trusty 🤖 and asked it how I could best avoid the pitfalls of this error.

I'll be honest, it was pretty sharp, effectively it had me move all the Firebase data into its own component and then annotate that as a client component. This is achieved by adding the 'use client' directive at the top of the file. Thus I have Analytics.tsx component that looks like this:

tsx
1'use client'; 2import { app } from '@/lib/firebase'; 3import { getAnalytics, isSupported } from 'firebase/analytics'; 4import { useEffect } from 'react'; 5 6export default function Analytics() { 7 useEffect(() => { 8 const initAnalytics = async () => { 9 if (await isSupported()) { 10 getAnalytics(app); 11 console.log('Firebase Analytics initialized'); 12 } 13 }; 14 15 initAnalytics(); 16 }, []); 17 18 return null; 19}

So, its basically using useEffect as a one-shot to fire up analytics, if it is supported, and doing so as a client component, since it'll need the window to do any real analyzing. The line containing the import from "@lib/firebase" is where the Firebase configuration lives and where it is initialized. This is a simple file that looks like this:

ts
1import { initializeApp } from 'firebase/app'; 2 3const firebaseConfig = { 4 apiKey: "----", 5 authDomain: "----", 6 projectId: "----", 7 storageBucket: "----", 8 messagingSenderId: "----", 9 appId: "----", 10 measurementId: "----" 11}; 12 13// Initialize Firebase 14export const app = initializeApp(firebaseConfig);

Now, of course, in my actual file, the identifiers are not "----", but you get the idea (these IDs are all straight from the Firebase console when I registered the app, see above). I don't actually think you are at a real security risk since these aren't the IDs that are use for actual access permissions, but I guess I'm overly cautious. I had a coworker once tell me, "Never apologize for anything...unless you leak API keys." 😆

Ultimately, then I import the Analytics component into my layout.tsx file and add it to the top of the page, like so:

tsx
1export default async function RootLayout({ 2 children, 3}: Readonly<{ 4 children: React.ReactNode; 5}>) { 6 const posts = await getPosts(); 7 const websiteJsonLd = generateWebsiteJsonLd(); 8 9 return ( 10 <html lang="en"> 11 <Head> 12 <script type="application/ld+json"> 13 {JSON.stringify(websiteJsonLd)} 14 </script> 15 </Head> 16 <body className={`${cinzel.variable} ${inter.variable} ${geistMono.variable} ${cormorantUnicase.variable}`}> 17 <NavBar posts={posts}/> 18 <main> 19 {children} 20 </main> 21 <Analytics /> 22 </body> 23 </html> 24 ); 25}

This is the just the rendering portion there is more to this file, but just to show where it lives in the layout. Once this was done, I'm not sure of another way to test it out other than deploy it and verify. My configuration now is that I do all my work in a dev branch and merge to main so I don't eat up my free build minutes on Netlify, until I'm really ready. Currently, I'm just checking that when I fire it up in the client, there is a console log that states "Firebase Analytics initialized", but I also doubled back to the Firebase web console and opened the site on mine and my wife's phones to verify the realtime "Active Users" data was going up. It worked so, it shipped. 🚀

One thing to note is that "non-realtime" analytics data can take 24-48 hours to show up in the Firebase console, so don't panic if it doesn't show up right away (like I did 😬).

Firebase Analytics dashboard showing an active user (me!) 🎉
Firebase Analytics dashboard showing an active user (me!) 🎉

Who knows maybe one day the stats will pickup and I'll get a whole 3-4 users show up! Or...my wife will have pity and go open the site on every computer in the public library...