Meta Integration Task Specification Figma: Overview We need to implement a Meta (Facebook) integration for our form builder platform. This will allow customers to trigger Meta Pixel events when users navigate between form pages or complete specific actions. Requirements Integration Configuration Create a new "Meta" entry in our Integrations section Allow multiple Meta configurations per account Each configuration should include: Meta Pixel ID (required) Access Token (for server-side API calls) Configuration name (for identification) Event Triggering Support both client-side and server-side event tracking Allow users to select a Meta configuration when setting up an event Provide a dropdown of standard Meta events and a "Custom" option For custom events, allow users to input their own event name and parameters Meta Standard Events Meta Pixel supports the following standard events: PageView ViewContent AddToCart AddToWishlist InitiateCheckout AddPaymentInfo Purchase Lead CompleteRegistration Contact CustomizeProduct Donate FindLocation Schedule StartTrial SubmitApplication Subscribe Technical Implementation Client-Side Implementation For client-side tracking, we'll need to: Initialize the Meta Pixel with the configured Pixel ID Create a utility function to trigger events import { useEffect } from 'react'; declare global { interface Window { fbq: any; } } // Initialize Meta Pixel export const initializeMetaPixel = (pixelId: string): void => { if (typeof window !== 'undefined') { // Add Facebook Pixel code !function(f,b,e,v,n,t,s) {if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); window.fbq('init', pixelId); } }; // Track client-side event export const trackMetaEvent = ( eventName: string, params?: Record<string, any> ): void => { if (typeof window !== 'undefined' && window.fbq) { window.fbq('track', eventName, params); } }; // React hook to initialize Meta Pixel export const useMetaPixel = (pixelId: string): void => { useEffect(() => { if (pixelId) { initializeMetaPixel(pixelId); } }, [pixelId]); }; Server-Side Implementation For server-side tracking, we'll create a tRPC procedure: import { z } from 'zod'; import axios from 'axios'; import { createTRPCRouter, protectedProcedure } from '../trpc'; export const metaEventsRouter = createTRPCRouter({ trackServerEvent: protectedProcedure .input( z.object({ pixelId: z.string(), accessToken: z.string(), eventName: z.string(), eventId: z.string().optional(), userData: z.object({ externalId: z.string().optional(), email: z.string().optional(), phone: z.string().optional(), // Add other user data fields as needed }).optional(), customData: z.record(z.any()).optional(), }) ) .mutation(async ({ input }) => { const { pixelId, accessToken, eventName, eventId, userData, customData } = input; const eventData = { data: [ { event_name: eventName, event_time: Math.floor(Date.now() / 1000), event_id: eventId, user_data: userData, custom_data: customData, action_source: 'website', }, ], }; try { const response = await axios.post( https://graph.facebook.com/v17.0/${pixelId}/events, eventData, { params: { access_token: accessToken, }, } ); return { success: true, data: response.data, }; } catch (error) { console.error('Error tracking Meta event:', error); return { success: false, error: error instanceof Error ? error.message : 'Unknown error', }; } }), }); Integration in Form Builder Example of how to use the Meta integration in the form builder: import { useState } from 'react'; import { useMetaPixel, trackMetaEvent } from '@/utils/metaPixel'; import { api } from '@/utils/api'; // Standard Meta events const META_STANDARD_EVENTS = [ 'PageView', 'ViewContent', 'AddToCart', 'Lead', 'CompleteRegistration', // ... other events 'Custom', ]; const IntegrationSelector = ({ formId, pageId, metaConfigurations }) => { const [selectedConfig, setSelectedConfig] = useState(null); const [selectedEvent, setSelectedEvent] = useState('PageView'); const [customEventName, setCustomEventName] = useState(''); // Initialize Meta Pixel if a configuration is selected useMetaPixel(selectedConfig?.pixelId); // tRPC mutation for server-side tracking const trackServerEvent = api.metaEvents.trackServerEvent.useMutation(); const handleTriggerEvent = async (formData) => { if (!selectedConfig) return; const eventName = selectedEvent === 'Custom' ? customEventName : selectedEvent; const eventData = { form_id: formId, page_id: pageId, // Add relevant form data ...formData, }; // Client-side tracking trackMetaEvent(eventName, eventData); // Server-side tracking (if access token is available) if (selectedConfig.accessToken) { await trackServerEvent.mutateAsync({ pixelId: selectedConfig.pixelId, accessToken: selectedConfig.accessToken, eventName, userData: { // Add user data if available externalId: formData.userId, email: formData.email, }, customData: eventData, }); } }; return ( <div> <h3>Meta Integration</h3> <div> <label>Select Configuration:</label> <select value={selectedConfig?.id || ''} onChange={(e) => { const config = metaConfigurations.find(c => c.id === e.target.value); setSelectedConfig(config); }} > <option value="">Select a configuration</option> {metaConfigurations.map(config => ( <option key={config.id} value={config.id}> {config.name} </option> ))} </select> <button>Create New Configuration</button> </div> <div> <label>Select Event:</label> <select value={selectedEvent} onChange={(e) => setSelectedEvent(e.target.value)} > {META_STANDARD_EVENTS.map(event => ( <option key={event} value={event}>{event}</option> ))} </select> {selectedEvent === 'Custom' && ( <input type="text" value={customEventName} onChange={(e) => setCustomEventName(e.target.value)} placeholder="Enter custom event name" /> )} </div> <button onClick={() => handleTriggerEvent({})}> Test Event </button> </div> ); }; export default IntegrationSelector; Database Schema Updates We'll need to add a new table/collection for Meta configurations: // ... existing code ... export const metaConfigurationsTable = pgTable('meta_configurations', { id: serial('id').primaryKey(), accountId: integer('account_id') .notNull() .references(() => accountsTable.id, { onDelete: 'cascade' }), name: varchar('name', { length: 255 }).notNull(), pixelId: varchar('pixel_id', { length: 255 }).notNull(), accessToken: varchar('access_token', { length: 255 }), createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at').defaultNow().notNull(), }); // ... existing code ... Next Steps Create the Meta configuration management UI Implement the Meta Pixel initialization logic Add Meta event selection to the form builder Implement client-side and server-side event tracking Add validation and error handling Write tests for the new functionality Technical Considerations Meta Pixel ID is required for both client and server-side tracking Access Token is only required for server-side API calls We should implement proper error handling for API failures Consider rate limiting for Meta API calls UI examples: Figma Design:
0 votes
Vote to help us prioritize this feature
Sign in to join the discussion
Sign in