Skip to content

fix: handle middle mouse button click - #58

Merged
vitonsky merged 2 commits into
masterfrom
27-click-links-with-middle-mouse-button-is-not-tracked
Mar 8, 2026
Merged

fix: handle middle mouse button click#58
vitonsky merged 2 commits into
masterfrom
27-click-links-with-middle-mouse-button-is-not-tracked

Conversation

@vitonsky

@vitonsky vitonsky commented Mar 8, 2026

Copy link
Copy Markdown
Owner

Fixes #27
Related to #57

Summary by CodeRabbit

  • Bug Fixes
    • Improved link click tracking to correctly ignore non-primary clicks while capturing primary and middle-button/auxiliary clicks for more accurate engagement analytics.
  • Tests
    • Added tests validating right-clicks are ignored and middle/auxiliary clicks are captured and sent.
  • Chores
    • Updated tooling/config to recognize the new auxiliary click event term.

@vitonsky vitonsky linked an issue Mar 8, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Mar 8, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds middle-click tracking by handling the browser's auxclick event and ignores non-primary (right/other) mouse buttons; retains anchor text extraction, optional predicate filtering, and Plausible event POSTs; cleans up both click and auxclick listeners on teardown.

Changes

Cohort / File(s) Summary
Link Click Tracking Plugin
src/plugins/enableLinkClicksCapture.ts
Adds MouseEvent.button checks to process only primary (0) and middle (1) clicks; wires an additional 'auxclick' listener and removes it during teardown.
Tests
src/plugins/enableLinkClicksCapture.test.ts
New tests validating right-clicks are ignored and middle-clicks (via auxclick) trigger a POST to Plausible API; mocks fetch and window.location.
Lint config
.eslintrc
Adds "auxclick" to spell-checker skipWords to avoid linting false positives for the new event name.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Browser
  participant Plugin
  participant PlausibleAPI
  rect rgba(200,200,255,0.5)
  User->>Browser: Click link (left or middle)
  Browser->>Plugin: dispatch 'click' or 'auxclick' event
  Plugin->>Plugin: check MouseEvent.button (0 or 1) & optional predicate
  alt allowed
    Plugin->>PlausibleAPI: POST /api/event (anchor text + props)
    PlausibleAPI-->>Plugin: 200 OK
  else ignored
    Plugin-->>Browser: no action
  end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • feat: score user sessions #55: Modifies src/plugins/enableLinkClicksCapture.ts to add auxclick handling and mouse-button filtering; touches the same plugin and functionality.

Poem

🐰
I hopped on a link with a middle-button spring,
The auxclick sang out — now the metrics sing.
Right-clicks I sniffed and politely denied,
Left and middle clicks now tracked with pride. 🥕🖱️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: handle middle mouse button click' directly addresses the main objective from issue #27 to track middle mouse button link clicks.
Linked Issues check ✅ Passed The code changes implement middle mouse button click tracking via auxclick events and ignore non-primary button clicks, fulfilling issue #27's requirement to track middle mouse button link clicks.
Out of Scope Changes check ✅ Passed All changes relate directly to handling middle mouse button clicks: adding auxclick event listeners, ignoring non-primary buttons, adding tests, and updating ESLint config for the new event term.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 27-click-links-with-middle-mouse-button-is-not-tracked

Comment @coderabbitai help to get the list of available commands and usage tips.

@vitonsky

vitonsky commented Mar 8, 2026

Copy link
Copy Markdown
Owner Author

@CodeRabbit could you generate the minimal test file for related changes. Only minimal unit test is needed. One-two test cases.

@coderabbitai

coderabbitai Bot commented Mar 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the PR diff to understand what changes were made
gh pr diff 58 --repo vitonsky/plausible-client

Length of output: 1230


🏁 Script executed:

#!/bin/bash
# Find existing test files to understand testing patterns
fd -e test.ts -e spec.ts -e test.tsx -e spec.tsx . --type f

# Also look for test config files
fd -e jest.config.js -e jest.config.ts -e vitest.config.ts -e vitest.config.js . --type f

# Check package.json for test framework and dependencies
cat package.json

Length of output: 1872


🏁 Script executed:

#!/bin/bash
# Look at the most related existing test file
cat src/plugins/enableAutoOutboundTracking.test.ts

# Also look at the source file being modified
cat src/plugins/enableLinkClicksCapture.ts

Length of output: 4624


@vitonsky: Here's a minimal test file for the two new behaviors introduced in this PR:

src/plugins/enableLinkClicksCapture.test.ts

// `@vitest-environment` jsdom

import { Plausible } from '../Plausible';
import { enableLinkClicksCapture } from './enableLinkClicksCapture';

const mockFetch = vi.fn();
globalThis.fetch = mockFetch;

const locationSpyon = vi.spyOn(window, 'location', 'get');

beforeEach(() => {
	vi.clearAllMocks();
	locationSpyon.mockReturnValue(new URL('https://example.org') as any as Location);
	mockFetch.mockReturnValue(new Response('ok'));

	document.body.innerHTML = `<a id="link" href="https://example.com">click me</a>`;
});

const plausible = new Plausible({
	apiHost: 'https://plausible.io',
	domain: 'example.org',
});

enableLinkClicksCapture(plausible);

test('Ignore right-click (button=2) on a link', () => {
	const anchorElm = document.querySelector('a#link') as HTMLAnchorElement;
	expect(anchorElm).toBeInstanceOf(HTMLAnchorElement);

	anchorElm.dispatchEvent(new MouseEvent('click', { button: 2, bubbles: true }));

	expect(mockFetch).not.toHaveBeenCalled();
});

test('Capture middle mouse button click via auxclick event', () => {
	const anchorElm = document.querySelector('a#link') as HTMLAnchorElement;
	expect(anchorElm).toBeInstanceOf(HTMLAnchorElement);

	anchorElm.dispatchEvent(new MouseEvent('auxclick', { button: 1, bubbles: true }));

	expect(mockFetch).toHaveBeenCalledTimes(1);
	expect(mockFetch).toHaveBeenCalledWith(
		'https://plausible.io/api/event',
		expect.objectContaining({
			method: 'POST',
		}),
	);
});

Two test cases:

  1. Right-click ignored — dispatches a click event with button: 2; the early-return guard should prevent sendEvent from being called.
  2. Middle-click captured — dispatches an auxclick event with button: 1 (the new listener); verifies that the analytics fetch is triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/plugins/enableLinkClicksCapture.ts`:
- Around line 55-60: The auxclick listener is registered in the bubbling phase
while click uses capture, causing asymmetric behavior; update the
addEventListener and removeEventListener calls for 'auxclick' to use the same
options object ({ capture: true }) as 'click' so that clickCallback is invoked
in the capture phase for both events (refer to the clickCallback registration
and the cleanup removal function).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b685a64c-6fa7-49a9-ad36-3e40fd08571a

📥 Commits

Reviewing files that changed from the base of the PR and between 194d9fa and a767ae7.

📒 Files selected for processing (1)
  • src/plugins/enableLinkClicksCapture.ts

Comment thread src/plugins/enableLinkClicksCapture.ts
@vitonsky
vitonsky merged commit 90ca950 into master Mar 8, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Click links with middle mouse button is not tracked

1 participant