• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
valdottown

valdottown

rage-clicks

Forward PostHog rage clicks to Discord
Public
Like
rage-clicks
Home
Code
3
README.md
H
main.ts
shell.ts
Branches
1
Pull requests
Remixes
History
Environment variables
1
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
README.md
Code
/
README.md
Search
…
Viewing readonly version of main branch: v19
View latest version
README.md

Rage Clicks Webhook β†’ Discord

Receive PostHog rage click events and forward them to Discord with human-readable alerts.

What are Rage Clicks?

Rage clicks occur when a user repeatedly clicks on something that doesn't respond as expected. They're a strong signal of user frustration and often indicate:

  • Broken buttons or links
  • Slow-loading UI elements
  • Confusing interface elements
  • Missing click handlers
  • Unresponsive form fields

Setup

1. Set up Discord Webhook

  1. In your Discord server, go to Server Settings β†’ Integrations β†’ Webhooks
  2. Click New Webhook and copy the webhook URL
  3. Add it to this val's environment variables as DISCORD_WEBHOOK_URL

2. Configure PostHog Webhook

  1. In PostHog, go to Data Pipelines β†’ Destinations β†’ Create Destination
  2. Select Webhook as the destination type
  3. Enter this val's endpoint URL: https://valdottown--rage-clicks.web.val.run
  4. Set up a filter for the $rageclick event

How it Works

When PostHog detects a rage click, it sends a webhook payload containing:

  • elements_chain: A complex CSS-selector-like string describing the clicked element
  • $current_url: The page URL where the rage click occurred
  • $pathname: The path portion of the URL
  • Browser/device details: Browser, OS, viewport size
  • Geo location: City, region, country (from $set.$geoip_* fields)
  • Session info: Session ID, entry URL, user ID

This val:

  1. Parses the elements_chain into a human-readable description
  2. Formats a Discord embed with all relevant context
  3. Sends an alert to your Discord channel

Elements Chain Parsing

The elements_chain from PostHog looks like:

button.px-4.py-2:attr__class="..."attr__type="submit"attr__text="Save";form...

This val parses it into friendly descriptions like:

Raw ElementParsed Description
button...attr__text="Save Changes""Save Changes" button
input...attr__name="key"attr__type="text""key" input field
svg.lucide.lucide-chevron-right...Chevron Right icon
a...attr__text="Docs"attr__href="/docs""Docs" link β†’ /docs
input...attr__type="checkbox"attr__name="agree""agree" checkbox

Example Discord Alert

The alert includes:

  • πŸ–±οΈ Clicked Element: Human-readable description of what was clicked
  • πŸ“ Page: The URL where it happened (clickable link)
  • 🌍 Location: User's geographic location
  • πŸ’» Device: Browser and OS info
  • πŸ“± Screen: Viewport dimensions
  • πŸ‘€ User ID: Identified or anonymous user
  • πŸšͺ Session Entry: Where the user started (if different from current page)

Testing

Run shell.ts to send a test rage click event to Discord without waiting for real events:

# In Val Town, just run shell.ts

The test file includes several sample scenarios you can switch between:

// Choose which sample to test: const eventToSend = sampleButtonClick; // "Save Changes" button // const eventToSend = sampleInputClick; // "key" input field // const eventToSend = sampleIconClick; // Chevron Right icon // const eventToSend = sampleLinkClick; // "Getting Started Guide" link

TypeScript Types

The val exports types and utilities you can use:

import type { PostHogRageClickEvent } from "https://esm.town/v/valdottown/rage-clicks/main.ts"; import { parseElementsChain } from "https://esm.town/v/valdottown/rage-clicks/main.ts"; // Parse any PostHog elements_chain into a human-readable format const element = parseElementsChain(event.elements_chain); console.log(element.description); // '"Save Changes" button' console.log(element.elementType); // 'button' console.log(element.text); // 'Save Changes'

PostHogRageClickEvent Type

interface PostHogRageClickEvent { event: { uuid: string; event: "$rageclick"; elements_chain: string; distinct_id: string; properties: { $current_url: string; $pathname: string; $browser: string; $browser_version: number; $os: string; $os_version: string; $device_type: string; $viewport_width: number; $viewport_height: number; $user_id?: string; $session_id?: string; $session_entry_pathname?: string; $set?: { $geoip_city_name?: string; $geoip_country_code?: string; $geoip_subdivision_1_name?: string; }; // ... more properties }; timestamp?: string; }; }

Files

  • main.ts - HTTP handler that receives webhooks and sends Discord alerts
  • shell.ts - Test script with sample rage click events for manual testing
  • README.md - This documentation

Customization

Adding PostHog Recording Link

If you want to link directly to session recordings, uncomment and configure the recording URL section in main.ts:

// Add link to PostHog recording if we have session_id if (props.$session_id) { const recordingUrl = `https://app.posthog.com/project/YOUR_PROJECT_ID/replay/${props.$session_id}`; fields.push({ name: "🎬 Session Recording", value: `[View in PostHog](${recordingUrl})`, inline: true, }); }

Replace YOUR_PROJECT_ID with your actual PostHog project ID.

FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
Β© 2025 Val Town, Inc.