EventsDocs
Everything you need to track events with the 4Paid pixel.
Add this snippet to your site's <head>. Replace the API key with yours from the Settings page.
<script src="https://4paid.com/pixel.js" data-api-key="YOUR_API_KEY" defer></script>
defer — loads asynchronously, never blocks rendering.
data-api-key — your project API key. Generate one in Settings → API Keys.
Works with any framework — Next.js, React, Vue, static HTML, Shopify, WordPress. The pixel auto-detects SPA navigation.
The pixel automatically tracks these interactions — no code needed.
element_clickClicks on buttons, links, and interactive elements.
{ tag: "button", text: "Buy Now", selector: ".cta-btn", id: "checkout" }outbound_clickClicks on links to external domains.
{ href: "https://stripe.com/docs", text: "Docs", hostname: "stripe.com" }form_submitAny form submission on the page.
{ formId: "signup", formName: "register", formAction: "/api/auth" }site_searchSearch queries detected from URL params (?q=, ?search=, etc).
{ query: "pricing plans" }clipboardCopy and paste actions on the page.
{ action: "copy", contentLength: 128 }file_downloadClicks on downloadable files (pdf, zip, csv, etc).
{ href: "/report.pdf", filename: "report.pdf", extension: "pdf" }product_viewedDetected from JSON-LD, meta tags, or Shopify globals.
{ name: "Wireless Headphones", price: 79.99, currency: "USD", brand: "Acme" }add_to_cartShopify fetch intercept, WooCommerce events, or cart form submissions.
{ name: "Wireless Headphones", price: 79.99, quantity: 1, variant: "Black" }checkout_startedFires when URL contains /checkout. Shopify enriches with cart total.
{ total: 159.98, currency: "USD", itemCount: 2, platform: "shopify" }purchaseOrder confirmation / thank-you pages. Shopify enriches with order details.
{ orderId: "5001", total: 159.98, currency: "USD", itemCount: 2 }media_startPlayback started. type distinguishes video from audio.
{ src: "/intro.mp4", type: "video", provider: "html5", duration: 124 }media_pausePaused mid-playback. Includes current position.
{ src: "/ep-12.mp3", type: "audio", provider: "html5", currentTime: 620, duration: 1840 }media_completePlayed to the end.
{ src: "https://youtube.com/embed/abc", type: "video", provider: "youtube", duration: 312 }media_milestoneFires at 25%, 50%, and 75% of playback.
{ src: "/course-lesson.mp4", type: "video", provider: "html5", percent: 50, duration: 480 }pageviewFires on every page load or client-side navigation. Sent as type "pageview" (not a custom event). Includes referrer, UTMs, and session count.
{ pathname: "/pricing", referrer: "https://google.com", sessionPageCount: 3 }page_leaveFires when the user navigates away or closes the tab. Includes active/idle engagement time.
{ timeOnPage: 34200, activeMs: 28000, idleMs: 6200, finalScrollDepth: 82, pathname: "/pricing" }page_load_timeCaptures page load timing from the Performance API after the load event completes.
{ loadTime: 1100, pathname: "/pricing" }web_vitalsLCP, CLS, and INP measured from real users.
{ lcp: 1240, cls: 0.03, inp: 85 }js_errorUncaught JS errors and unhandled promise rejections.
{ message: "Cannot read property 'id' of null", filename: "/app.js", lineno: 42 }identifyLinks a visitor to a known user ID via _4p.identify(). All past and future events are tied to this identity.
{ userId: "usr_abc123", traits: { plan: "pro", email: "[email protected]" } }Send custom events from your app with a single line of code.
track("event_name", { ...props })track("waitlist_joined", { ref: "blog", tier: "pro" })import { track } from "@/lib/track"
// Track after successful auth
const { error } = await signUp.email({ name, email, password })
if (!error) track("signup_success", { method: "email" })
// Track onboarding progress
track("onboarding_step", { step: 3, name: "connect_domain" })Track specific interactions by CSS, ID, or URL — no code needed. Create triggers from the Triggers tab.
css: .plan-card[data-tier] | id: dark-mode-toggleCSS selector, ID, class, or text content
id: api-key-form | action: /api/webhooksID, class, CSS, or form action URL
css: .pricing-table | id: onboarding-bannerFire when element scrolls into view
/dashboard/*/settings | /docs/api/*Contains, starts with, exact, or regex
Every key-value pair attached to any event shows up here — from custom events, pixel auto-capture, and registered properties. All aggregated, all filterable.
Properties come from the second argument to track(), or use register() to auto-attach properties to every event without repeating yourself.
Instead of adding the same properties to every track() call, register them once. They merge into every event until you unregister. Persists across page loads.
register({ plan: "pro", role: "admin" }) // auto-attached to all eventsunregister("plan") // stop attachingimport { register, unregister } from "@/lib/track"
// Set once after login — attaches to every future event
register({ staffId: "staff_42", plan: "pro", role: "admin" })
// Now every track() call automatically includes staffId, plan, role
track("page_view") // → { staffId: "staff_42", plan: "pro", role: "admin" }
// Remove a property (e.g. on logout)
unregister("staffId")Link anonymous visitors to known users with identify(). Pass a user ID and any traits — the pixel ties all past and future events to that identity.
Call once after login. Any traits you pass are stored with the user and shown here.
identify("user_id", { anyTrait: "anyValue", ... })identify("usr_1", { email: "[email protected]", name: "Sarah" })identify("usr_1", { plan: "pro", role: "admin" })Links anonymous visitor to your user ID
Any traits you pass are stored with the user
All past & future events tied to this identity
import { identify } from "@/lib/track"
// After login — link this visitor to your user record
identify("usr_a1b2c3", {
email: "[email protected]",
name: "Sarah Chen",
plan: "pro",
company: "Acme Inc",
})