Analytics is the process of collecting and analyzing data about how visitors interact with your website. This information is crucial because it allows you to make informed decisions to improve your website. Google Analytics is a great choice but there could be data privacy as well as GDPR compliance concerns. When choosing an analytics tool, it's important that it: is free (open source) allows self hosting (no vendor lock in) is GDPR compliant is light weight & fast Umami Analytics checks all these boxes. Umami Analytics : An open source analytics solution Umami Analytics is a simple, fast, and privacy-focused tool that lets you track website usage without compromising user privacy. It is an open-source alternative to Google Analytics. A big plus is that Umami analytics is GDPR (General Data Protection Regulation) compliant. There are two options to use UMAMI analytics use UMAMI cloud solutions (paid with free tier plan) Self host on your server In this article we are going to explore self hosting option. We are going to use Supabase (free tier plan) for database (postgres) and Vercel (free tier/hobby plan) for hosting Umami. Let us dive into how to self host Umami analytics using Vercel + Supabase for free 1. Create new project in Supabase Create a new account (if you don’t already have one) with Supabase and create new project by pressing + New Project Provide project name as you like (eg. your_app_name-analytics) Don’t forget to store password somewhere, it would be needed later. Select a region nearest to the location of hosting server. 2. Initial Configuration for Supabase Select the project, navigate to SQL editor Copy the SQL scripts provided in the github repo Paste it on the SQL editor and click on run You’ll be able to see newly created tables on Table Editor option Navigate to Project Settings → Database → Connection String → Copy Connection URL 3. Fork UMAMI on github Fork the https://github.com/umami-software/umami project to your GitHub account. Edit db/postgresql/schema.prisma file (add directUrl) datasource db { provider = "postgresql" url = env("DATABASE_URL") directUrl = env("DIRECT_DATABASE_URL") //add this line relationMode = "prisma" } 4. Deploy on Vercel Go to Dashboard on Vercel and create new project From the dashboard page click Import Project then specify the URL to your fork of the project on GitHub. Before clicking on Deploy add the following environment variables DATABASE_URL = postgres://[user]:[password]@aws-0-[aws-region].pooler.supabase.com:6543/postgres?**pgbouncer=true&connection_limit=1** DIRECT_DATABASE_URL = postgres://[user]:[password]@aws-0-[aws-region].pooler.supabase.com:**5432**/postgres Important!! 💡 DATABASE_URL is same as the Connection Url copied from supabase (in step 2) but you have to add ?pgbouncer=true&connect_timeout=1 at the end of Url 💡 DATABASE_URL is same as the Connection Url copied from supabase (in step 2) but you have to replace the port from 6543 to 5432 After that click on deploy 5. Resolving Error “The database Schema is not empty” In step two we did run a sql script in Supabase which created few tables in the database. Now when script is run during deployment it throws an error with error code P3005 saying Database schema is not empty To resolve this, clone your forked repository in your local and add the same environment variables as mentioned above (in step 4) Now run the following commands (to install dependencies and setup db connection) yarn install yarn build-db Then we would create a baseline migration by following below step If you have a prisma/migrations folder, delete, move, rename, or archive this folder. Run the following command to create a migrations directory inside with your preferred name. This example will use 01_init for the migration name: mkdir -p prisma/migrations/01_init Generate a migration and save it to a file using prisma migrate diff npx prisma migrate diff \ --from-empty \ --to-schema-datamodel prisma/schema.prisma \ --script > prisma/migrations/01_init/migration.sql Run the prisma migrate resolve command for each migration that should be ignored: npx prisma migrate resolve --applied 01_init This command adds the target migration to the _prisma_migrations table and marks it as applied. When you run prisma migrate deploy to apply new migrations, Prisma Migrate: Skips all migrations marked as 'applied', including the baseline migration Applies any new migrations that come after the baseline migration You will be able to successfully deploy the app on Vercel server after this. The URL of your analytics app would be available under project tab of Vercel app. 6. Login to Umami The default credentials for login is username : admin password : umami To change the default credentials navigate to settings → users → admin → edit Enter your new password and click on save. 7. Configure your website for analytics tracking navigate to settings → websites → + Add website Name : provide any name of your choice Domain : your [website](https://www.invoizly.com) domain (eg. invoizly.com) Once website is added navigate to settings → website → your website name → edit → tracking code. Copy the tracking code. 8. Add tracking code to your project In Next.JS projects to load a third-party script for multiple routes, import next/script and include the script directly in your layout component: import Script from 'next/script' export default function Layout({ children, }: { children: React.ReactNode }) { return ( <html lang="en" className="dark"> <body className={cn(`${inter.className} antialiased`)}> <Navbar /> {children} <Footer /> </body> <Script defer src="https://[your-analytics-app].vercel.app/script.js" data-website-id="xxxx-xxx-xxxx-xxxx-xxxxx" /> </> ) } After adding the Sript in your root layout, deploy your app and visit your web page. you will be able to track the visits on your analytics dashboard page. Conclusion Hope with help of this article you will be able to set up analytics for your application quickly and easily, without relying on third-party services. Since Vercel and Supabase both provides generous free tier, you can run your analytics for free in the initial days while being GDPR compliant. About Invoizly Invoizly is all about making invoicing easy and free. With Invoizly, you can quickly create high-quality, customizable invoices that look professional. It’s designed to be super user-friendly, so you can focus on your business instead of getting bogged down in paperwork. Analytics is the process of collecting and analyzing data about how visitors interact with your website. This information is crucial because it allows you to make informed decisions to improve your website. Analytics Google Analytics is a great choice but there could be data privacy as well as GDPR compliance concerns. When choosing an analytics tool, it's important that it: is free (open source) allows self hosting (no vendor lock in) is GDPR compliant is light weight & fast is free (open source) allows self hosting (no vendor lock in) is GDPR compliant is light weight & fast Umami Analytics checks all these boxes. Umami Analytics : An open source analytics solution Umami Analytics is a simple, fast, and privacy-focused tool that lets you track website usage without compromising user privacy. It is an open-source alternative to Google Analytics. A big plus is that Umami analytics is GDPR (General Data Protection Regulation) compliant. Umami Analytics There are two options to use UMAMI analytics use UMAMI cloud solutions (paid with free tier plan) Self host on your server use UMAMI cloud solutions (paid with free tier plan) Self host on your server In this article we are going to explore self hosting option. We are going to use Supabase (free tier plan) for database (postgres) and Vercel (free tier/hobby plan) for hosting Umami. Let us dive into how to self host Umami analytics using Vercel + Supabase for free 1. Create new project in Supabase Create a new account (if you don’t already have one) with Supabase and create new project by pressing + New Project Provide project name as you like (eg. your_app_name-analytics) Don’t forget to store password somewhere, it would be needed later. Select a region nearest to the location of hosting server. Create a new account (if you don’t already have one) with Supabase and create new project by pressing + New Project Create a new account (if you don’t already have one) with Supabase and create new project by pressing + New Project + New Project Provide project name as you like (eg. your_app_name-analytics) Provide project name as you like (eg. your_app_name-analytics ) your_app_name-analytics Don’t forget to store password somewhere, it would be needed later. Don’t forget to store password somewhere, it would be needed later. Select a region nearest to the location of hosting server. Select a region nearest to the location of hosting server. 2. Initial Configuration for Supabase Select the project, navigate to SQL editor Copy the SQL scripts provided in the github repo Select the project, navigate to SQL editor Select the project, navigate to SQL editor Copy the SQL scripts provided in the github repo Copy the SQL scripts provided in the github repo github Paste it on the SQL editor and click on run Paste it on the SQL editor and click on run You’ll be able to see newly created tables on Table Editor option You’ll be able to see newly created tables on Table Editor option Table Editor Navigate to Project Settings → Database → Connection String → Copy Connection URL Navigate to Project Settings → Database → Connection String → Copy Connection URL 3. Fork UMAMI on github Fork the https://github.com/umami-software/umami project to your GitHub account. Edit db/postgresql/schema.prisma file (add directUrl) datasource db { provider = "postgresql" url = env("DATABASE_URL") directUrl = env("DIRECT_DATABASE_URL") //add this line relationMode = "prisma" } Fork the https://github.com/umami-software/umami project to your GitHub account. Fork the https://github.com/umami-software/umami project to your GitHub account. https://github.com/umami-software/umami Edit db/postgresql/schema.prisma file (add directUrl) datasource db { provider = "postgresql" url = env("DATABASE_URL") directUrl = env("DIRECT_DATABASE_URL") //add this line relationMode = "prisma" } Edit db/postgresql/schema.prisma file (add directUrl) db/postgresql/schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") directUrl = env("DIRECT_DATABASE_URL") //add this line relationMode = "prisma" } datasource db { provider = "postgresql" url = env("DATABASE_URL") directUrl = env("DIRECT_DATABASE_URL") //add this line relationMode = "prisma" } 4. Deploy on Vercel Go to Dashboard on Vercel and create new project From the dashboard page click Import Project then specify the URL to your fork of the project on GitHub. Before clicking on Deploy add the following environment variables Go to Dashboard on Vercel and create new project From the dashboard page click Import Project then specify the URL to your fork of the project on GitHub. Before clicking on Deploy add the following environment variables DATABASE_URL = postgres://[user]:[password]@aws-0-[aws-region].pooler.supabase.com:6543/postgres?**pgbouncer=true&connection_limit=1** DIRECT_DATABASE_URL = postgres://[user]:[password]@aws-0-[aws-region].pooler.supabase.com:**5432**/postgres DATABASE_URL = postgres://[user]:[password]@aws-0-[aws-region].pooler.supabase.com:6543/postgres?**pgbouncer=true&connection_limit=1** DIRECT_DATABASE_URL = postgres://[user]:[password]@aws-0-[aws-region].pooler.supabase.com:**5432**/postgres Important!! 💡 DATABASE_URL is same as the Connection Url copied from supabase (in step 2) but you have to add ?pgbouncer=true&connect_timeout=1 at the end of Url ?pgbouncer=true&connect_timeout=1 💡 DATABASE_URL is same as the Connection Url copied from supabase (in step 2) but you have to replace the port from 6543 to 5432 6543 5432 After that click on deploy After that click on deploy 5. Resolving Error “The database Schema is not empty” In step two we did run a sql script in Supabase which created few tables in the database. Now when script is run during deployment it throws an error with error code P3005 saying Database schema is not empty To resolve this, clone your forked repository in your local and add the same environment variables as mentioned above (in step 4) Now run the following commands (to install dependencies and setup db connection) yarn install yarn build-db Then we would create a baseline migration by following below step In step two we did run a sql script in Supabase which created few tables in the database. Now when script is run during deployment it throws an error with error code P3005 saying Database schema is not empty In step two we did run a sql script in Supabase which created few tables in the database. Now when script is run during deployment it throws an error with error code P3005 saying Database schema is not empty P3005 Database schema is not empty To resolve this, clone your forked repository in your local and add the same environment variables as mentioned above (in step 4) To resolve this, clone your forked repository in your local and add the same environment variables as mentioned above (in step 4) Now run the following commands (to install dependencies and setup db connection) yarn install yarn build-db Now run the following commands (to install dependencies and setup db connection) yarn install yarn build-db yarn install yarn build-db Then we would create a baseline migration by following below step Then we would create a baseline migration by following below step baseline migration If you have a prisma/migrations folder, delete, move, rename, or archive this folder. Run the following command to create a migrations directory inside with your preferred name. This example will use 01_init for the migration name: mkdir -p prisma/migrations/01_init Generate a migration and save it to a file using prisma migrate diff npx prisma migrate diff \ --from-empty \ --to-schema-datamodel prisma/schema.prisma \ --script > prisma/migrations/01_init/migration.sql Run the prisma migrate resolve command for each migration that should be ignored: npx prisma migrate resolve --applied 01_init This command adds the target migration to the _prisma_migrations table and marks it as applied. When you run prisma migrate deploy to apply new migrations, Prisma Migrate: Skips all migrations marked as 'applied', including the baseline migration Applies any new migrations that come after the baseline migration If you have a prisma/migrations folder, delete, move, rename, or archive this folder. If you have a prisma/migrations folder, delete, move, rename, or archive this folder. Run the following command to create a migrations directory inside with your preferred name. This example will use 01_init for the migration name: mkdir -p prisma/migrations/01_init Run the following command to create a migrations directory inside with your preferred name. This example will use 01_init for the migration name: migrations 01_init mkdir -p prisma/migrations/01_init mkdir -p prisma/migrations/01_init Generate a migration and save it to a file using prisma migrate diff npx prisma migrate diff \ --from-empty \ --to-schema-datamodel prisma/schema.prisma \ --script > prisma/migrations/01_init/migration.sql Generate a migration and save it to a file using prisma migrate diff prisma migrate diff npx prisma migrate diff \ --from-empty \ --to-schema-datamodel prisma/schema.prisma \ --script > prisma/migrations/01_init/migration.sql npx prisma migrate diff \ --from-empty \ --to-schema-datamodel prisma/schema.prisma \ --script > prisma/migrations/01_init/migration.sql Run the prisma migrate resolve command for each migration that should be ignored: npx prisma migrate resolve --applied 01_init This command adds the target migration to the _prisma_migrations table and marks it as applied. When you run prisma migrate deploy to apply new migrations, Prisma Migrate: Skips all migrations marked as 'applied', including the baseline migration Applies any new migrations that come after the baseline migration Run the prisma migrate resolve command for each migration that should be ignored: prisma migrate resolve npx prisma migrate resolve --applied 01_init npx prisma migrate resolve --applied 01_init This command adds the target migration to the _prisma_migrations table and marks it as applied. When you run prisma migrate deploy to apply new migrations, Prisma Migrate: _prisma_migrations prisma migrate deploy Skips all migrations marked as 'applied', including the baseline migration Applies any new migrations that come after the baseline migration Skips all migrations marked as 'applied', including the baseline migration Skips all migrations marked as 'applied', including the baseline migration Applies any new migrations that come after the baseline migration Applies any new migrations that come after the baseline migration You will be able to successfully deploy the app on Vercel server after this. The URL of your analytics app would be available under project tab of Vercel app. You will be able to successfully deploy the app on Vercel server after this. The URL of your analytics app would be available under project tab of Vercel app. project 6. Login to Umami The default credentials for login is The default credentials for login is username : admin password : umami username : admin password : umami To change the default credentials navigate to settings → users → admin → edit Enter your new password and click on save. To change the default credentials navigate to settings → users → admin → edit Enter your new password and click on save. 7. Configure your website for analytics tracking navigate to settings → websites → + Add website navigate to settings → websites → + Add website + Add website Name : provide any name of your choice Domain : your [website](https://www.invoizly.com) domain (eg. invoizly.com) Name : provide any name of your choice Domain : your [website](https://www.invoizly.com) domain (eg. invoizly.com) Once website is added navigate to settings → website → your website name → edit → tracking code. Copy the tracking code. Once website is added navigate to settings → website → your website name → edit → tracking code. Copy the tracking code. 8. Add tracking code to your project In Next.JS projects to load a third-party script for multiple routes, import next/script and include the script directly in your layout component: third-party script next/script import Script from 'next/script' export default function Layout({ children, }: { children: React.ReactNode }) { return ( <html lang="en" className="dark"> <body className={cn(`${inter.className} antialiased`)}> <Navbar /> {children} <Footer /> </body> <Script defer src="https://[your-analytics-app].vercel.app/script.js" data-website-id="xxxx-xxx-xxxx-xxxx-xxxxx" /> </> ) } import Script from 'next/script' export default function Layout({ children, }: { children: React.ReactNode }) { return ( <html lang="en" className="dark"> <body className={cn(`${inter.className} antialiased`)}> <Navbar /> {children} <Footer /> </body> <Script defer src="https://[your-analytics-app].vercel.app/script.js" data-website-id="xxxx-xxx-xxxx-xxxx-xxxxx" /> </> ) } After adding the Sript in your root layout, deploy your app and visit your web page. you will be able to track the visits on your analytics dashboard page. Conclusion Hope with help of this article you will be able to set up analytics for your application quickly and easily, without relying on third-party services. Since Vercel and Supabase both provides generous free tier, you can run your analytics for free in the initial days while being GDPR compliant. About Invoizly Invoizly is all about making invoicing easy and free. With Invoizly, you can quickly create high-quality, customizable invoices that look professional. It’s designed to be super user-friendly, so you can focus on your business instead of getting bogged down in paperwork. Invoizly