TekOnline

Investigating a Strange Singapore Traffic Spike in GA4, WordPress, and Nginx Proxy Manager

I noticed something odd in Google Analytics: Singapore had suddenly become one of the largest sources of traffic to this site.

At first glance, that sounded exciting. Maybe there was international interest in the ESPHome HVAC controllers, 24VAC relay boards, or Home Assistant content. But the numbers felt strange enough that I wanted to check before making business decisions from them.

This post walks through how I investigated it using GA4, the GA4 Data API, Docker, WordPress, and Nginx Proxy Manager logs on an Oracle Cloud instance.

The Initial GA4 Signal

In GA4, Singapore was showing hundreds of active users over a recent 30-day period.

The country report looked something like this:

  • Singapore: high hundreds of active users
  • Australia: several hundred active users
  • United States: several hundred active users
  • Other countries: much smaller numbers

That was enough to ask a useful question:

Are these real people looking at products, or is this automated traffic?

First Pass: What Were Singapore Visitors Looking At?

Using the GA4 Data API, I pulled reports filtered to:

  • Country: Singapore
  • Date range: last 30 days
  • Dimensions: landing page, page path, source/medium, device, events

The first useful finding was that most Singapore sessions were not product-focused.

The top pages were mostly broad technical posts and the homepage:

  • Homepage
  • Windows / WSL / Docker posts
  • VS Code and development posts
  • Home Assistant and ESP32 posts
  • A small number of WooCommerce product pages

There was some product activity, but not much:

  • A few product page views
  • A small number of view_item events
  • A couple of add_to_cart events
  • No checkout starts
  • No purchases

That made it look less like strong buying intent and more like broad crawling or automated browsing.

The GA4 Bot Fingerprint

The deeper GA4 checks made the traffic look much more suspicious.

The Singapore sessions were mostly:

  • Direct traffic with no referrer
  • New users only
  • Desktop
  • Windows
  • Chrome
  • Same or near-identical screen resolution
  • Very high engagement rate

One of the strongest signals was the screen resolution pattern. A large majority of Singapore users reported the same unusual resolution:

1280x1200

Real users normally produce a messy mix of screen sizes, browsers, devices, and returning/new-user behavior. This was too uniform.

At that point, GA4 was strongly suggesting automation, but GA4 does not expose IP addresses. To confirm it, I needed server logs.

GA4 Does Not Show Visitor IPs

This is worth stating clearly:

GA4 does not expose visitor IP addresses in reports or through the Data API.

That means you cannot use GA4 alone to answer:

  • Which IPs caused this?
  • Which hosting providers were involved?
  • Was it cloud infrastructure?
  • Was it a crawler?
  • Was it a VPN?

For that, you need server-side logs.

In this case, the site is running as a Docker stack behind Nginx Proxy Manager on an Oracle Cloud instance.

Finding the Right Nginx Proxy Manager Log

The WordPress container itself was not the best first place to look. The useful log was at the reverse proxy layer.

Nginx Proxy Manager writes per-proxy-host access logs. On this server they were under:

/data/nginxproxymanager/data/logs/

The TekOnline proxy host had its own access log:

proxy-host-3_access.log

The log format included useful fields:

  • Timestamp
  • HTTP status
  • Method
  • Host
  • Path
  • Client IP
  • Response length
  • Upstream target
  • User agent
  • Referrer

That gave much better visibility than GA4.

What the Server Logs Showed

The server logs confirmed the suspicion.

The Singapore-attributed traffic was mostly coming from cloud, crawler, hosting, or VPN networks, including providers such as:

  • Huawei Cloud
  • Oracle Cloud
  • UpCloud
  • Linode / Akamai
  • DigitalOcean
  • GoDaddy
  • VPN-labelled networks

The request patterns were also not customer-like.

Common paths included:

/wp-login.php
/xmlrpc.php
//xmlrpc.php
//wp-includes/wlwmanifest.xml
/inputs.php
/wp-content/users.php
/wp-content/plugins/.../wp_filemanager.php

Those are classic WordPress scanner and exploit-probe paths.

Some crawlers identified themselves clearly, for example:

PetalBot
DotBot
MJ12bot
GPTBot
ClaudeBot

Others used generic browser user agents, old browser strings, Java HTTP clients, or no user agent at all.

The Conclusion

The Singapore spike was not strong evidence of Singapore customer demand.

It was mostly:

  • Automated traffic
  • WordPress login probing
  • XML-RPC probing
  • Scanner traffic
  • Cloud-hosted crawlers
  • VPN/proxy traffic
  • Known bots indexing or scraping the site

There may still have been a small amount of real traffic mixed in, but the big number in GA4 was not something I should treat as a market signal.

That is the important lesson:

Country-level GA4 traffic can look like demand, but server logs may tell a very different story.

What I Changed

Rather than blocking Singapore entirely, I created a small Nginx Proxy Manager hardening snippet focused on the exact bad paths seen in the logs.

The goal was to block obvious garbage without affecting:

  • Public product pages
  • Blog posts
  • WooCommerce cart
  • WooCommerce checkout
  • WordPress REST API
  • admin-ajax.php

Example rules:

location = /xmlrpc.php {
    access_log off;
    return 403;
}

location ~* ^/+/xmlrpc\.php$ {
    access_log off;
    return 403;
}

location = /inputs.php {
    access_log off;
    return 403;
}

location = /wp-content/users.php {
    access_log off;
    return 403;
}

location = /wp-content/plugins/hellopress/wp_filemanager.php {
    access_log off;
    return 403;
}

location ~* ^/wp-content/plugins/.*/(wp_filemanager|filemanager|file-manager)\.php$ {
    access_log off;
    return 403;
}

location = /wp-includes/wlwmanifest.xml {
    access_log off;
    return 403;
}

I deliberately did not block /wp-login.php in that basic snippet. Login protection needs a more careful approach.

Better Protection for WordPress Admin

For WordPress admin pages, a better approach is to put an authentication layer in front of them.

In my case, I already run Authentik, so a sensible next step is:

  • Put /wp-login.php behind Authentik
  • Put /wp-admin/ behind Authentik
  • Do not block /wp-admin/admin-ajax.php
  • Leave WooCommerce checkout, cart, product pages, and public content alone

That matters because WordPress and WooCommerce use admin-ajax.php for legitimate frontend behavior. Blocking all of /wp-admin/ blindly can break parts of the public site.

Another good option is Cloudflare Turnstile on risky forms:

  • WordPress login
  • Registration
  • Contact forms
  • Comments
  • WooCommerce account login/register

I would not add a JavaScript challenge to every public page unless the site was under serious abuse. Public product and blog pages should remain fast and easy to index.

What I Would Do Next

My preferred layered setup is:

  1. Block obvious exploit paths at Nginx.
  2. Disable or block XML-RPC unless something genuinely needs it.
  3. Put WordPress admin/login behind Authentik or another access layer.
  4. Use Turnstile or a security plugin for forms and login.
  5. Keep public product and blog pages open.
  6. Monitor logs for a week and adjust based on real evidence.

I would avoid broad country blocking. The problem was not “Singapore”. The problem was cloud, crawler, VPN, and scanner traffic geolocated to Singapore.

Business Lesson

The most useful part of this investigation was not the bot blocking. It was avoiding a bad interpretation of analytics.

At first, the GA4 country report looked like possible international product demand. After digging deeper, it was clear that most of the traffic was not commercial intent.

The right response is not:

“Singapore is a big market for us now.”

The right response is:

“Add lightweight international enquiry tracking, but validate demand through real form submissions, checkout starts, and orders.”

Analytics are useful, but only when paired with server logs and a bit of skepticism.


Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *