How Do I Style and Track Lead Widgets with Custom Code?

IN BRIEF 
This article is for developers and technical users who want to go beyond the standard Lead Widget configuration. It covers injecting custom CSS to restyle a widget, the stable selectors available for that styling, and how to capture widget events in an analytics platform such as Google Tag Manager, Google Analytics 4 (GA4), or Meta Pixel. If you only need to create, style, and embed a widget through the interface, see How Do I Create and Manage Lead Widgets? instead.

Overview

The Lead Widget is built for safe embedding and flexible tracking. Two design choices shape how you extend it with code:

  • The widget uses Shadow DOM for style encapsulation, which means your website's CSS will not affect the widget, and the widget's CSS will not affect your website. You restyle the widget only through its own custom CSS attributes, targeting its stable selectors.
  • The widget is analytics-agnostic. It emits standard browser CustomEvents for its major interactions but does not integrate with any analytics platform directly. Your site listens for those events and routes them wherever you need.

Back to top

Step-by-Step Instructions

Before You Begin

  • Create and save a Custom widget, then generate its embed code, as described in How Do I Create and Manage Lead Widgets?.
  • Custom CSS is applied through attributes on the widget's embed code, so you need access to edit that embed code on your site.
  • Event tracking requires the ability to add scripts to your website, either directly or through a tag manager.

Back to top

Installing the attribution tracking snippet

Copy the attribution snippet from Office Portal and paste it into your website. The snippet is the script itself — an inline block of code — rather than a link to a file hosted by iClassPro.

Paste the whole block exactly as it is copied. Do not swap it for a reference to a hosted script.

Once installed, the snippet carries the marketing parameters from the address a visitor first arrived on — gclid or utm_source, for example — onto links they click on your own site and onto links pointing to iClassPro. If a destination link already has one of those values set, the existing value is kept and the rest are added.

The snippet does not set cookies and stores nothing in the browser. It reads only the address of the page the visitor is currently on. Because of that, consent tools that block third-party trackers should not stop it from working.

If a visitor arrives with no marketing parameters in the address, the snippet leaves their links alone.

Back to top

Custom CSS Injection

Advanced users can inject custom CSS using the widget's configuration attributes:

  • lcw-custom-css for inline CSS, and
  • lcw-custom-css-url for an external CSS file.

Important Note(s): Only inject CSS rules that target the widget-specific selectors listed below. Do not inject your entire website stylesheet, as this can cause conflicts and unexpected behavior. Always use the stable data-lcw-* selectors when targeting elements.

Back to top

Available selectors

Use these stable data-lcw-* attributes to target widget elements.

  • [data-lcw-widget] targets the entire widget container.
  • [data-lcw-content] targets the content wrapper inside the widget.
  • [data-lcw-state="form"] targets the form state container.
  • [data-lcw-state="success"] targets the success state container.
  • [data-lcw-form] targets the form element.
  • [data-lcw-form-section] targets the template-defined form surface section, such as the modern or split body panel.
  • [data-lcw-field="first_name"] targets the wrapper for the first name field.
  • [data-lcw-field="last_name"] targets the wrapper for the last name field
  • [data-lcw-field="email"] targets the wrapper for the email field
  • [data-lcw-field="phone"] targets the wrapper for the phone field
  • [data-lcw-input="first_name"] targets the text input field for the first name field.
  • [data-lcw-input="last_name"] targets the text input field for the last name field
  • [data-lcw-input="email"] targets the text input field for the email field
  • [data-lcw-input="phone"] targets the text input field for the phone field
  • [data-lcw-textarea] targets the message textarea.
  • [data-lcw-char-counter] targets the message character counter, such as "42 / 255".
  • [data-lcw-button] targets the submit button.
  • [data-lcw-header] targets the header area.
  • [data-lcw-footer] targets the footer area.
  • [data-lcw-row] targets a specific row area in a horizontal layout.
  • [data-lcw-sidebar] targets a specific sidebar area in a split layout.
  • [data-lcw-heading] targets the main heading text.
  • [data-lcw-subheading] targets the subheading text.
  • [data-lcw-icon] targets the icon element.
  • [data-lcw-consent] targets the consent checkbox area.
  • [data-lcw-checkbox] targets the consent checkbox input.
  • [data-lcw-checkbox-visual] targets the visual checkbox element.
  • [data-lcw-consent-text] targets the legal text label.
  • [data-lcw-error] targets validation error messages.
  • [data-lcw-bubble] targets the floating bubble button.
  • [data-lcw-modal] targets the popup window container.
  • [data-lcw-welcome] targets the welcome prompt tooltip, with [data-lcw-welcome-message] for its text and [data-lcw-welcome-close] for its close button.
  • [data-lcw-success] targets the success screen, with [data-lcw-success-icon] for the icon circle, [data-lcw-success-greeting] for the "Thank You!" text, and [data-lcw-success-message] for the thank you message.

Back to top

Analytics & Event Tracking

The widget emits standard browser CustomEvents for all major interactions, so a host site can integrate with any analytics platform. The widget does not integrate with any platform directly, so the host site handles its own integration.

Back to top

Available events

  • lcw:load fires after the widget renders, and includes widgetId, orgCode, sourceUrl, templateType, and widgetType.
  • lcw:formStart fires on the first typing, and includes widgetId, orgCode, and sourceUrl.
  • lcw:formSubmit fires on form submission, and includes widgetId, orgCode, sourceUrl, success, and errorType.
  • lcw:modalOpen fires when a floating widget is opened, and includes widgetId and orgCode.
  • lcw:modalClose fires when a floating widget is closed, and includes widgetId and orgCode.
  • lcw:welcomeDismiss fires when the welcome prompt is dismissed, and includes widgetId and orgCode.

Note(s): For discoverability and TypeScript support, the event constants are available at window.LeadCaptureWidget.events.

Back to top

Integration Instructions

Integration Method 1: Google Tag Manager (Recommended)

For non-technical users who already have GTM installed. This is the simplest approach - add a bridge script once, then configure triggers/tags in GTM's no-code UI.

Back to top

Step 1: Add Bridge Script

Add this one-time setup script to your website:

<script> 
// Lead Capture Widget → GTM Bridge 
// Add this once to your site template 
(function() { 
  var events = ['load', 'formStart', 'formSubmit', 'modalOpen', 'modalClose', 'welcomeDismiss']; 
 
  events.forEach(function(eventName) { 
    document.addEventListener('lcw:' + eventName, function(e) { 
      window.dataLayer = window.dataLayer || []; 
      window.dataLayer.push({ 
        event: 'lcw_widget_' + eventName, 
        lcw_widget_id: e.detail.widgetId, 
        lcw_org_code: e.detail.orgCode, 
        lcw_source_url: e.detail.sourceUrl, 
        lcw_success: e.detail.success, 
        lcw_error_type: e.detail.errorType, 
        lcw_template_type: e.detail.templateType, 
        lcw_widget_type: e.detail.widgetType 
      }); 
    }); 
  }); 
})(); 
</script> 
 

Where to place this script:

  • WordPress: Add to your theme's header.php or use a plugin like "Insert Headers and Footers"
  • Squarespace: Settings → Advanced → Code Injection → Header
  • Wix: Dashboard → Settings → Custom Code → Add Code to Head
  • Custom HTML: Add to your site's <head> section, before your GTM container script

Step 2: Configure GTM Triggers

In your GTM workspace:

  1. Create Trigger for form submissions:
    • Type: Custom Event
    • Event name: lcw_widget_formSubmit
    • Fires on: All Custom Events
  2. Create Variables to access event data:
    • Variable Type: Data Layer Variable
    • Data Layer Variable Name: lcw_widget_id (or any other field)
  3. Create Tags that use these triggers:
    • GA4 Event tag, Meta Pixel tag, or any other platform

No additional coding is required after the bridge script is in place.

Back to top

Integration Method 2: Direct Google Analytics (GA4)

For sites using GA4 directly (without GTM). Add event listeners after your GA4 initialization script:

<script> 
// Track widget form submissions in GA4 
document.addEventListener('lcw:formSubmit', function(e) { 
  if (typeof gtag !== 'undefined') { 
    gtag('event', 'lead_submission', { 
      widget_id: e.detail.widgetId, 
      org_code: e.detail.orgCode, 
      success: e.detail.success, 
      source_url: e.detail.sourceUrl 
    }); 
  } 
}); 
 
// Track widget loads 
document.addEventListener('lcw:load', function(e) { 
  if (typeof gtag !== 'undefined') { 
    gtag('event', 'widget_load', { 
      widget_id: e.detail.widgetId, 
      template_type: e.detail.templateType 
    }); 
  } 
}); 
 
// Track form starts (when user begins filling out form) 
document.addEventListener('lcw:formStart', function(e) { 
  if (typeof gtag !== 'undefined') { 
    gtag('event', 'form_start', { 
      widget_id: e.detail.widgetId 
    }); 
  } 
}); 
</script> 

Back to top

Integration Method 3: Meta Pixel

For sites using Meta (Facebook) Pixel. Add event listeners after your Meta Pixel base code:

<script> 
// Track lead submissions to Meta Pixel 
document.addEventListener('lcw:formSubmit', function(e) { 
  if (typeof fbq !== 'undefined' && e.detail.success) { 
    fbq('track', 'Lead', { 
      content_name: 'Lead Capture Widget', 
      widget_id: e.detail.widgetId 
    }); 
  } 
}); 
 
// Track form starts as custom event 
document.addEventListener('lcw:formStart', function(e) { 
  if (typeof fbq !== 'undefined') { 
    fbq('trackCustom', 'WidgetFormStart', { 
      widget_id: e.detail.widgetId 
    }); 
  } 
}); 
</script>  

Back to top

Integration Method 4: Multiple Platforms at Once

Listen to events once and route to multiple platforms:

<script> 
document.addEventListener('lcw:formSubmit', function(e) { 
  var detail = e.detail; 
 
  // Google Analytics 4 
  if (typeof gtag !== 'undefined') { 
    gtag('event', 'lead_submission', { 
      widget_id: detail.widgetId, 
      success: detail.success 
    }); 
  } 
 
  // Meta Pixel 
  if (typeof fbq !== 'undefined' && detail.success) { 
    fbq('track', 'Lead'); 
  } 
 
  // Custom analytics 
  if (typeof yourAnalytics !== 'undefined') { 
    yourAnalytics.track('Widget Submission', detail); 
  } 
}); 
</script>  

Back to top

Event Deduplication

  • Widget Load and Form Start events are deduplicated per session per widget (using sessionStorage). They fire once per browser session per widget instance.
  • Form Submit, Modal Open/Close, and Welcome Dismiss events fire every time.

Back to top

Browser Support

  • Chrome 60 and later.
  • Firefox 60 and later.
  • Safari 12 and later.
  • Edge 79 and later.

Back to top

Troubleshooting & FAQs

  • Where can I find a complete list of available analytics events?
    • Refer to window.LeadCaptureWidget.events in the browser console for the full list of event constants.
  • Why is my inline widget not rendering?
    • Confirm that the container <div> has an id that begins with lcw-, and that lcw-widget-id is included in the script attributes.
  • Which analytics platforms are supported?
    • The widget is analytics-agnostic, so any platform is supported through its CustomEvents. This article provides ready-to-use examples for Google Tag Manager, GA4, and Meta Pixel.
  • Can I inject my whole website stylesheet into the widget?
    • No. Target only the widget-specific data-lcw-* selectors. Injecting a full stylesheet can cause conflicts and unexpected behavior.
  • Do I need to replace a snippet I installed earlier?
    • Snippets installed earlier keep working, and they also stopped using cookies and browser storage. Replacing an old snippet with the current one from Office Portal is recommended but not required.

Back to top

Related Articles

Back to top

Need more assistance?

Customer support is available at 1-877-554-6776.

Sunday 3 PM – 12 AM CT
Monday–Thursday 9 AM – 12 AM CT
Friday–Saturday 9 AM – 6 PM CT.