Back

How we made Plausible analytics work with ad blockers

Captain's log, stardate d13.y42/AB

MarsBased CTO Tutorials
Xavier Redó
Founder & CTO
How we made Plausible analytics work with ad blockers

Over the past few months at MarsBased, we have been putting a lot of effort into improving everything around our company's marketing efforts.

With the arrival of David Cajal, our first 100% marketing-focused hire, we have gained both time and bandwidth to level up many areas: improving our podcast, refreshing the website, being more consistent on social media, and starting to work much more deeply and deliberately with metrics. All of this has one clear goal: promoting MarsBased better and attracting new clients.

As part of this broader effort, we have made several improvements to the website. One of the steps we took was reinstalling a web analytics tool, as we already mentioned in a previous post. We chose Plausible because it gives us valuable insights into website traffic and user behavior while being fully privacy-focused: no tracking cookies, no personal data storage, and no way to identify individual users.

However, many privacy-focused browsers and ad-blocking extensions block Plausible events altogether.

For us, though, this was particularly painful. MarsBased is not a company with millions of monthly visits. When you work with huge numbers, it is much easier to extrapolate trends, understand what works, and spot what doesn't. With small or medium-sized volumes, every missing data point hurts, and drawing reliable conclusions becomes much harder.

On top of that, our target audience, potential hires and people interested in technology and product development, tends to be especially privacy-conscious. It is no surprise that a significant portion of our visitors (we’d estimate well over 50%) use ad blockers or privacy-first browsers.

To work around this issue, we decided to build a small proxy that routes all Plausible-related requests through our own web server. Instead of sending events directly from the browser to Plausible, our frontend sends them to our backend, and from there our application forwards them to Plausible.

Because these requests originate from our own domain and backend, most ad blockers and privacy tools no longer block them.

This approach isn't new: it is quite common in marketing setups with Google Analytics, for example. We simply hadn't done it yet with Plausible. Given that our traffic volume is relatively modest, we were able to implement this solution directly in our backend. Our website runs on Ruby on Rails, so the implementation lives there.

Below, we're sharing this implementation in case it is useful to someone else. And if this gets some traction or interest, we might even package it as an open-source Ruby gem so it can be easily reused in any Ruby on Rails application.

Routes

get '/js/script.js', to: 'plausible_proxy#script'
post '/api/event', to: 'plausible_proxy#event'

class PlausibleProxyController < ApplicationController
  # The requests from Plausible don't send the Rails CSRF token
  skip_forgery_protection

  SCRIPT_PATH = '/js/script.tagged-events.outbound-links.js'
  TIMEOUT = 5

  def script
    return head :not_found unless Rails.env.production?

    response = HTTParty.get(
      "https://#{plausible_host}#{SCRIPT_PATH}",
      timeout: TIMEOUT
    )

    if response.success?
      expires_in 1.day, public: true
      render plain: response.body, content_type: 'application/javascript'
    else
      head :bad_gateway
    end
  rescue StandardError => e
    Rails.logger.error("Plausible script fetch error: #{e.message}")
    head :bad_gateway
  end

  def event
    return head :not_found unless Rails.env.production?

    response = HTTParty.post(
      "https://#{plausible_host}/api/event",
      body: request.raw_post,
      headers: {
        'Content-Type' => 'application/json',
        'User-Agent' => request.user_agent,
        'X-Forwarded-For' => forwarded_ip
      },
      timeout: TIMEOUT
    )

    head response.code
  rescue StandardError => e
    Rails.logger.error("Plausible proxy error: #{e.message}")
    head :bad_gateway
  end

  private

  def plausible_host
    ENV.fetch('PLAUSIBLE_HOST', Rails.application.config.x.plausible_host)
  end

  def forwarded_ip
    request.remote_ip || request.ip
  end
end

That said, it is important to be clear about the limitations. If our website had high or very high traffic, this approach wouldn't be the right fit. In that scenario, it would make much more sense to run a fully dedicated proxy service (written in a language with stronger async capabilities) and put a proper reverse proxy like Nginx or Cloudflare in front of it, routing requests to different services based on the URL.

For our current scale, though, this solution hits the sweet spot.

Share this post

Related articles

Metal works

Code refactoring: when, why and who

While code refactoring is cool and appealing, it's not the right choice always.

Read full article
Robot staring at the camera - possibly your next CTO

Why does your startup not need a CTO (just yet)

Going for a CTO way too early in the life of your startup may be detrimental to your success. Learn why.

Read full article
Astronaut

Switching to Plausible: A privacy-friendly analytics tool for MarsBased

At MarsBased, we value privacy, simplicity, and open‑source tools. We replaced Google Analytics with Plausible, a lightweight, privacy‑first solution. This shift keeps us GDPR‑compliant while still providing the insights we need.

Read full article