A native macOS menu bar application that displays real-time Google Analytics 4 visitor counts.
- Real-time visitor counts - See active users directly in your menu bar
- Last updated timestamp - Know exactly when data was last refreshed
- Native macOS app - Built with Swift and SwiftUI, no Electron or web views
- Secure authentication - Uses Google service account with local credential storage
- Configurable refresh - Choose polling intervals from 5 to 60 seconds
- Minimal footprint - Menu bar only, no dock icon
- macOS 15 (Sequoia) or later
- Xcode 16+ (for building from source)
- Swift 6.0+
- Python 3 with Pillow (auto-installed for icon generation)
- Google Analytics 4 property with Real-Time API access
- Google Cloud service account with Analytics Data API enabled
- Go to Google Cloud Console
- Create a new project or select an existing one
- Navigate to APIs & Services > Library
- Search for "Google Analytics Data API" and enable it
- In Google Cloud Console, go to IAM & Admin > Service Accounts
- Click Create Service Account
- Enter a name (e.g., "pulsert-reader")
- Click Create and Continue
- Skip the optional permissions step (no special roles needed)
- Click Done
- Click on the newly created service account
- Go to the Keys tab
- Click Add Key > Create new key
- Select JSON format
- Click Create - the key file will download automatically
- Keep this file secure - it provides API access
- Go to Google Analytics
- Select your GA4 property
- Navigate to Admin > Property Access Management
- Click the + button to add users
- Enter the service account email (ends with
@*.iam.gserviceaccount.com) - Set role to Viewer (minimum required)
- Click Add
-
Create the configuration directory:
mkdir -p ~/.config/pulsert -
Move your downloaded service account JSON file:
mv ~/Downloads/your-project-*.json ~/.config/pulsert/credentials.json
-
Set appropriate file permissions:
chmod 600 ~/.config/pulsert/credentials.json
# Clone the repository
git clone https://github.com/charlesjones-dev/pulsert.git
cd pulsert
# Open in Xcode
open PulseRT.xcodeproj
# Build and run (Cmd+R)Or build from command line:
xcodebuild -project PulseRT.xcodeproj -scheme PulseRT -configuration ReleaseUse the build script to create and install a standalone .app:
# Build only
./build.sh
# Build and install to /Applications
./build.sh --installThe --install flag will:
- Generate the app icon (pink background with "RT" initials)
- Build a release version
- Kill any running PulseRT instance
- Copy the app to
/Applications/ - Remove the quarantine attribute (so Gatekeeper won't block it)
To customize the icon colors, edit generate-icon.py and change BG_COLOR or FG_COLOR, then rebuild.
If you copied the app manually without removing the quarantine attribute, macOS will block it. To open:
- Open System Settings > Privacy & Security
- Scroll to Security - you'll see PulseRT was blocked
- Click Open Anyway, then Open in the confirmation dialog
Or right-click the app in Finder, select Open, and click Open in the dialog.
- Click the PulseRT icon in your menu bar
- Select Settings...
- Enter your GA4 Property ID (numeric, found in GA4 Admin > Property Details)
- Optionally set a display name
- Choose your preferred refresh interval
- Click Save
PulseRT stores configuration in ~/.config/pulsert/:
| File | Purpose |
|---|---|
credentials.json |
Google service account key (required) |
config.json |
App settings - property ID, refresh interval (auto-created) |
| Setting | Description | Default |
|---|---|---|
| Property ID | GA4 property numeric ID | None (required) |
| Display Name | Friendly name shown in menu | Property ID |
| Refresh Interval | Polling frequency | 10 seconds |
Ensure ~/.config/pulsert/credentials.json exists and contains a valid service account key.
# Check file exists
ls -la ~/.config/pulsert/credentials.json
# Verify JSON is valid
cat ~/.config/pulsert/credentials.json | python3 -m json.tool- Verify the Analytics Data API is enabled in Google Cloud Console
- Check that the service account key hasn't been deleted or rotated
- Ensure the JSON file is the complete, unmodified download from Google
- Confirm the service account has Viewer access to the GA4 property
- Verify the Property ID is correct (numeric ID, not measurement ID)
- Check if your site has any active visitors (test by opening your site)
The Real-Time API has usage limits. Try increasing the refresh interval to 30 or 60 seconds.
- Check System Settings > Control Center > Menu Bar Only
- Ensure no other apps are hiding menu bar items
- Try quitting and relaunching PulseRT
- Go to Google Analytics
- Select your property
- Click Admin (gear icon)
- Under Property column, click Property Details
- Copy the Property ID (numeric value like
123456789)
Note: This is different from the Measurement ID (which starts with "G-").
- Service account credentials are stored locally, never transmitted except to Google
- No data is collected or sent to third parties
- The app requests only
analytics.readonlyscope (minimum required) - See SECURITY.md for credential handling best practices
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
MIT License - see LICENSE for details.
Created by Charles Jones
PulseRT - Real-time analytics at a glance