Requirements
| WordPress | 6.2 or higher |
|---|---|
| PHP | 7.4 or higher |
| License | GPL-2.0-or-later |
| External Dependencies | None. No API keys, no third-party services |
Installation
From WordPress.org
- In your WordPress admin go to Plugins → Add New
- Search for Click Counter
- Click Install Now then Activate
Manual Upload
- Download the ZIP file from WordPress.org or your account
- Go to Plugins → Add New → Upload Plugin
- Choose the ZIP and click Install Now
- Click Activate
Updating
Updates appear in Dashboard → Updates. Update like any other plugin. All your tracked selectors, click data, and settings are preserved during updates.
Uninstalling
Deactivate and delete from the Plugins screen. The plugin's database tables (wp_clicco_selectors and wp_clicco_clicks) remain after deletion. Delete those tables manually via phpMyAdmin if you want a clean removal.
Quick Start
Start tracking clicks in under 2 minutes:
- Go to Click Counter in your WordPress admin sidebar
- Click the Add Click Tracker button
- Click the picker icon next to the selector field to open the visual element picker, or type a CSS selector manually (e.g.
.buy-buttonor#signup-form) - If using the picker: your site opens in a new window with a purple highlight overlay — click the element you want to track
- Give the tracker a friendly name like “Buy Button” (optional but recommended)
- Click Save
Click Counter Tab
This is the main dashboard you see when you open the plugin. It lists all your tracked elements in a table.
Table Columns
| Element Identifier | The CSS selector being tracked (e.g. .buy-button, #hero > a) |
|---|---|
| Name | The optional friendly name you gave the tracker |
| Clicks | Total number of clicks recorded for this selector |
| Goal | A progress bar showing current clicks vs. your goal target. Only visible if goal tracking is enabled |
| Actions | Edit, Reset, and Delete buttons |
Actions Explained
- Edit — Opens a modal where you can change the selector, name, or goal settings
- Reset — Deletes all click data for this tracker but keeps the tracker itself. Also resets the goal notification flag so you can receive the goal email again
- Delete (×) — Permanently removes the tracker and all its click data
- Reset All Counts — Clears click data for every tracker at once. The trackers themselves remain
Visual Element Picker
The element picker lets you select elements to track visually without writing CSS selectors.
How to Use
- Click Add Click Tracker (or Edit an existing tracker)
- Click the customizer icon next to the selector input
- A new browser window opens showing your live site
- A small blue control box appears at the bottom-right with a toggle switch
- Hover over any element — it highlights in purple
- Click the element you want to track
- The window closes and the CSS selector is automatically filled in
Picker Controls
| Toggle Switch | Turn the picker on/off without closing the window. When off, you can browse your site normally |
|---|---|
| Hover Highlight | Purple overlay shows the exact element that will be selected |
| Click | Captures the selector and sends it back to the admin form |
How Selectors Are Generated
The picker generates CSS selectors using a smart algorithm:
- If the element has an ID, it uses that (e.g.
#signup-btn) since IDs are unique - If no ID, it builds a path using tag names and classes (e.g.
div.hero > a.cta-button) - It uses
:nth-child()when sibling elements share the same tag to ensure uniqueness - It walks up the DOM tree until it finds a selector that matches exactly one element
manage_options capability). Regular visitors never see it.Goal Tracking
Set click targets for any tracker and receive an email when the goal is reached.
Setting Up a Goal
- Add or edit a tracker
- Toggle Enable Goal Tracking on
- Enter your target in the Goal (clicks) field (e.g. 1000)
- Enter a Notification Email address
- Click Save
Goal Progress
Trackers with goals show a visual progress bar in the Click Counter tab displaying current clicks vs. the target (e.g. 750/1000) with a percentage-based fill.
Email Notifications
- A WordPress cron job checks goals once daily (runs as part of the daily cleanup task)
- When total clicks meet or exceed the goal count, an email is sent
- The email includes the selector, name, goal count, current count, and a link to your analytics page
- Each goal only sends one notification — it won't email you repeatedly
Analytics & Charts
The Analytics tab provides a visual chart, detailed click logs, and data export.
Chart
A bar chart at the top shows clicks per day for your selected date range. Hover over any bar to see the exact date and click count.
Filters
| Tracker | Filter by a specific tracker or select “All Trackers” to see combined data |
|---|---|
| From / To | Date range for the chart and export. Defaults to the last 30 days |
| Apply | Refreshes the chart with your current filter settings |
Click Logs
Below the chart is a paginated table showing every individual click event:
| ID | Unique click record ID |
|---|---|
| Tracker | The tracker name and CSS selector |
| Page | The page URL where the click happened (if page URL tracking is enabled) |
| Time | Timestamp of the click |
| Action | Delete button to remove individual log entries |
The log table shows 50 entries per page with pagination controls.
CSV Export
Export click data for use in Excel, Google Sheets, or other tools.
How to Export
- Go to the Analytics tab
- Set your desired filters (tracker and date range)
- Click the Export CSV button
- A CSV file downloads immediately
CSV Columns
The export includes: Selector, Name, Page URL, Page Title, and Clicked At.
Self Ignore Tab
Exclude your own clicks from being tracked by setting a browser cookie.
How to Enable
- Go to Click Counter → Self Ignore
- Your current status is displayed (tracking or ignored)
- Click Enable Ignore or visit the provided URL
- Your clicks are now excluded
How It Works
- Sets a cookie called
clicco_ignorein your browser - The cookie lasts 400 days
- Works automatically across all tabs and windows in the same browser
- You must enable it separately in different browsers (Chrome, Firefox, etc.) since cookies are not shared between browsers
- Does not persist in incognito/private browsing mode
Sharing With Team Members
Copy the Enable Ignore URL from the Self Ignore tab and share it with colleagues or clients. When they visit the URL, their clicks are excluded from that browser going forward.
Disabling Ignore
When the ignore cookie is active, the Self Ignore tab shows a Disable Ignore button and URL. Visit it to remove the cookie and start tracking your clicks again.
Settings Tab
General Settings
| Exclude All Logged-in Users | When enabled, clicks from any logged-in user are not tracked regardless of their role. Default: Off |
|---|
Exclude by User Role
Selectively exclude specific roles from tracking. A grid of checkboxes shows all registered roles on your site (Administrator, Editor, Author, Contributor, Subscriber, plus any custom roles from plugins like WooCommerce).
Tracking Options
| Track Page URL | Record which page the click occurred on. This data appears in your Analytics logs and CSV exports. Default: On |
|---|
Data Management
| Data Retention (days) | Automatically deletes click records older than this many days via a daily cron job. Set to 0 to keep data forever. Default: 90 days |
|---|---|
| Rate Limit (per IP/hour) | Maximum number of clicks recorded from a single IP address per hour. Helps prevent spam and click inflation. Set to 0 for unlimited. Default: 100 |
Shortcode Reference
The Settings tab also shows the shortcode syntax for displaying click counts on the frontend:
[click_count selector=".buy-button"]— Display count by CSS selector[click_count id="1"]— Display count by tracker ID
Shortcode
Use the [click_count] shortcode to display live click counts anywhere on your site.
Parameters
selector | The CSS selector of the tracker. Example: [click_count selector=".buy-button"] |
|---|---|
id | The tracker's database ID. Example: [click_count id="5"] |
Use one or the other — if both are provided, id takes priority. The shortcode outputs a plain number formatted with your locale's number separators (e.g. “1,234”).
Usage Examples
Social proof on a product page
🔥 [click_count selector=".add-to-cart"] people added this to their cartDownload counter
This file has been downloaded [click_count selector=".download-btn"] timesMultiple counters on one page
Downloads: [click_count selector=".download-btn"]Signups: [click_count selector=".signup-btn"]Contact clicks: [click_count id="3"]How It Works
Frontend Tracking
- When a page loads, the plugin outputs a lightweight inline JavaScript tracker (no external JS files)
- The script uses event delegation — a single click listener on
document.bodychecks every click against all your saved selectors usingelement.closest() - When a click matches, the tracker sends data to
admin-ajax.phpusing the sendBeacon API (falls back tofetchwithkeepalive: true) - The server validates the nonce, checks bot detection, checks rate limits, verifies the selector exists in the database, and records the click
Database Tables
wp_clicco_selectors | Stores tracked selectors, friendly names, and goal settings (goal_enabled, goal_count, goal_email, goal_notified) |
|---|---|
wp_clicco_clicks | Stores individual click events with selector_id, page_url, page_title, ip_hash, user_agent, user_id, and clicked_at timestamp |
Performance Notes
- Single event listener for all selectors via delegation — no matter how many trackers you add
- sendBeacon is non-blocking and doesn't delay page navigation or slow down the visitor experience
- Database indexes on selector_id and clicked_at for fast analytics queries
- Daily cron cleanup automatically purges old data per your retention setting
- No external JavaScript files loaded — the tracker is injected inline
Bot Detection
The plugin automatically filters out clicks from bots and crawlers to keep your data accurate.
What Gets Filtered
- Known bots: Googlebot, Bingbot, Yandex, Baidu, DuckDuckGo, and more
- SEO tools: Semrush, Ahrefs, Mj12bot, Dotbot, Petalbot
- Social crawlers: Facebook, LinkedIn, Twitter bots
- Monitoring services: Pingdom, UptimeRobot
- Automation tools: Selenium, Puppeteer, Playwright, PhantomJS
- Scripting agents: wget, curl, Python, Java, PHP, Ruby, Perl
- Empty or suspiciously short user agents (under 20 characters)
Bot detection runs server-side on every AJAX click request. If a bot is detected, the click is silently discarded.
Rate Limiting
Prevents a single visitor from inflating your click counts.
- Default: 100 clicks per IP address per hour
- Configurable in Settings → Data Management
- Set to
0to disable rate limiting - IP addresses are stored as SHA-256 hashes (never in plaintext) using your site's
AUTH_SALTfor the hash key - Works with Cloudflare, reverse proxies, and load balancers by checking
CF-Connecting-IP,X-Real-IP, andX-Forwarded-Forheaders in priority order
Privacy & Data
What Is Stored
| CSS Selector | ✅ The element identifier you configured |
|---|---|
| Click Timestamp | ✅ Date and time of each click |
| Page URL & Title | ✅ Optional — can be disabled in Settings |
| IP Address | ⚠️ Stored as a one-way SHA-256 hash only (for rate limiting). The actual IP is never saved |
| User Agent | ✅ Used for bot detection, stored truncated to 500 characters |
| User ID | ✅ Only for logged-in users (WordPress user ID) |
| Names, Emails, Personal Data | ❌ Never collected from visitors |
Where Data Is Stored
Everything is stored locally in your WordPress database. No data is sent to external servers or third parties.
External Connections
| Goal notification emails | Sent via your WordPress email configuration (wp_mail). No external email service is used |
|---|
Data Retention
Click records are automatically deleted after the configured retention period (default 90 days) via a daily cron job. Set retention to 0 to keep data indefinitely.
Troubleshooting
Clicks aren't being counted
- Verify the CSS selector is correct: open your browser DevTools console and run
document.querySelector('.your-selector')— it should return the element - Make sure you clicked Save after adding the tracker
- Check if you're being excluded: are you logged in with an excluded role? Is the self-ignore cookie active? Is “Exclude All Logged-in Users” enabled?
- Clear all caching (browser cache, page cache plugins, CDN cache) and hard-refresh with
Ctrl+Shift+R - Open the browser console (F12) and check for JavaScript errors
- The element must exist in the DOM when the page loads. Dynamically injected elements (loaded via AJAX after page load) may not be caught
Element picker window doesn't open
- Your browser's popup blocker is likely preventing the window. Look for a blocked popup notification in the address bar
- Allow popups for your WordPress admin domain and try again
- Alternative: skip the picker and type the CSS selector manually. Use your browser's DevTools inspector to find the right selector
Element picker opens but nothing highlights
- Make sure the toggle switch in the bottom-right blue box is turned on
- Check that
sessionStorageis available (some privacy extensions block it) - The picker only works for admin users with
manage_optionscapability
Goal notification email not received
- Confirm the goal is enabled, the target count is set, and the email address is correct
- Goals are checked once per day by WordPress cron as part of the daily cleanup task. If your cron isn't running reliably, consider a real cron job or a cron monitoring plugin
- Check your spam/junk folder
- Test that WordPress can send emails at all (try the built-in test or install a mail plugin)
- Each goal only sends one email. If you already received it, reset the tracker's count to re-arm the notification
Analytics chart is empty
- Make sure the date range covers dates when clicks actually occurred
- Try setting the Tracker filter to “All Trackers”
- Verify clicks are being recorded in the Click Counter tab
- If you just installed the plugin, wait for some real traffic to generate data
Self-ignore isn't working
- Check that your browser allows cookies (some privacy settings or extensions block them)
- Incognito/private mode uses temporary cookies that don't persist between sessions
- The cookie is domain-specific: if your site uses
www.example.com, enabling ignore onexample.com(without www) won't work - You must enable ignore separately in each browser you use
CSV export is incomplete
- Exports are limited to 10,000 records. Use a narrower date range to export in smaller batches
- Make sure the date range in the filters matches the data you expect
Conflict with caching plugins
- The plugin uses WordPress nonces which can break when served from cache. Exclude
admin-ajax.phpfrom caching - If click counts seem frozen, clear all caches and test again
- Object caching shouldn't affect tracking since clicks go directly to the database