Skip to content

feat(components): add MetaPixel component with event tracking#5

Merged
jontsai merged 3 commits intomasterfrom
feat/meta-pixel
Feb 26, 2026
Merged

feat(components): add MetaPixel component with event tracking#5
jontsai merged 3 commits intomasterfrom
feat/meta-pixel

Conversation

@jontsai
Copy link
Member

@jontsai jontsai commented Feb 26, 2026

Summary

Adds a reusable Meta Pixel (Facebook Pixel) component for Next.js sites.

Features

  • MetaPixel component with parameterized pixelId prop
  • trackMetaEvent() helper for standard events (Lead, Purchase, PageView, etc.)
  • trackMetaCustomEvent() helper for custom events
  • Follows same patterns as the existing GoogleAnalytics component
  • Full TypeScript support with proper Window interface extension

Usage

// In _app.tsx or layout.tsx
import { MetaPixel } from "@hacktoolkit/nextjs-htk/components"

<MetaPixel pixelId="1234567890123456" />
// Track events anywhere
import { trackMetaEvent } from "@hacktoolkit/nextjs-htk/components"

trackMetaEvent("Lead")
trackMetaEvent("Purchase", { value: 99.99, currency: "USD" })

- Add MetaPixel component for easy Meta (Facebook) Pixel integration
- Parameterized pixelId prop for different sites
- Include trackMetaEvent() and trackMetaCustomEvent() helpers
- Support all standard Meta Pixel events (Lead, Purchase, etc.)
- Follow same patterns as GoogleAnalytics component
- TypeScript support with proper Window interface extension
Copilot AI review requested due to automatic review settings February 26, 2026 08:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a Meta Pixel (Facebook Pixel) component for Next.js applications, following the same patterns as the existing GoogleAnalytics component. It provides a declarative way to integrate Facebook Pixel tracking with proper TypeScript support and event tracking helpers.

Changes:

  • Added MetaPixel component with configurable pixel ID, load strategy, and PageView tracking options
  • Exported tracking helper function trackMetaEvent() for programmatic event tracking
  • Extended Window interface with TypeScript definitions for the fbq function

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
packages/core/src/components/index.ts Exports the new MetaPixel component
packages/core/src/components/MetaPixel.tsx Implements the MetaPixel component with initialization script, noscript fallback, event tracking helper, and TypeScript types

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +85 to +89
fbq: (
action: string,
eventName: string,
params?: Record<string, unknown>
) => void
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

The TypeScript Window interface extension for fbq is incomplete. The Facebook Pixel fbq function supports multiple actions ('init', 'track', 'trackCustom', etc.), but the current type definition only supports 'track'. This will cause TypeScript errors when using fbq('init', pixelId) as seen on line 40. The function signature should be updated to support multiple overloads or use a more flexible type that accommodates all fbq actions.

Suggested change
fbq: (
action: string,
eventName: string,
params?: Record<string, unknown>
) => void
fbq(
action: 'init',
pixelId: string,
options?: Record<string, unknown>
): void
fbq(
action: 'track' | 'trackCustom',
eventName: string,
params?: Record<string, unknown>
): void
fbq(action: string, ...args: unknown[]): void

Copilot uses AI. Check for mistakes.
Comment on lines +69 to +80
export function trackMetaEvent(
eventName: string,
params?: Record<string, unknown>
) {
if (typeof window !== 'undefined' && typeof window.fbq === 'function') {
if (params) {
window.fbq('track', eventName, params)
} else {
window.fbq('track', eventName)
}
}
}
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

The PR description mentions a trackMetaCustomEvent() helper function, but this function does not exist in the code. Only trackMetaEvent() is implemented. Either the PR description should be updated to remove this reference, or the function should be added to match the documentation. Note that Facebook Pixel distinguishes between standard events (using fbq('track', eventName)) and custom events (using fbq('trackCustom', eventName)).

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +68
/**
* Track a Meta Pixel event
* Call this function to track custom events after the pixel is loaded
*
* @example
* // Standard event
* trackMetaEvent('Lead')
* trackMetaEvent('Purchase', { value: 99.99, currency: 'USD' })
*
* // Custom event
* trackMetaEvent('CustomEvent', { custom_param: 'value' })
*/
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

The documentation comment states this function can be used for custom events (line 66-67), but the implementation only uses fbq('track', ...) which is for standard events. Custom events in Facebook Pixel should use fbq('trackCustom', eventName, params). This could lead to confusion or incorrect event tracking. Consider either updating the implementation to handle custom events differently or clarifying in the documentation that this function is for standard events only.

Copilot uses AI. Check for mistakes.
Comment on lines +74 to +78
if (params) {
window.fbq('track', eventName, params)
} else {
window.fbq('track', eventName)
}
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

The conditional logic to check if params exists is unnecessary. Facebook Pixel's fbq function accepts an optional third parameter, so window.fbq('track', eventName, params) can be called even when params is undefined. This simplifies the code and removes the redundant if-else branch.

Suggested change
if (params) {
window.fbq('track', eventName, params)
} else {
window.fbq('track', eventName)
}
window.fbq('track', eventName, params)

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +52
<noscript>
<img
height="1"
width="1"
style={{ display: 'none' }}
src={`https://www.facebook.com/tr?id=${pixelId}&ev=PageView&noscript=1`}
alt=""
/>
</noscript>
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

When disablePageView is true, the JavaScript code skips PageView tracking, but the noscript fallback image still includes 'ev=PageView' in the URL. This creates inconsistent behavior between JavaScript and non-JavaScript environments. The noscript fallback should respect the disablePageView prop and conditionally render based on its value, or omit the 'ev' parameter when PageView tracking is disabled.

Suggested change
<noscript>
<img
height="1"
width="1"
style={{ display: 'none' }}
src={`https://www.facebook.com/tr?id=${pixelId}&ev=PageView&noscript=1`}
alt=""
/>
</noscript>
{!disablePageView && (
<noscript>
<img
height="1"
width="1"
style={{ display: 'none' }}
src={`https://www.facebook.com/tr?id=${pixelId}&ev=PageView&noscript=1`}
alt=""
/>
</noscript>
)}

Copilot uses AI. Check for mistakes.
- Add trackMetaCustomEvent() for custom events (uses fbq('trackCustom'))
- Fix TypeScript Window.fbq types with proper overloads
- Simplify trackMetaEvent() - remove unnecessary conditional
- Respect disablePageView in noscript fallback
- Update JSDoc to clarify standard vs custom events
@jontsai jontsai merged commit 755611b into master Feb 26, 2026
1 check passed
@jontsai jontsai deleted the feat/meta-pixel branch February 26, 2026 08:23
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.

2 participants