Skip to content

Component Name: reCaptcha

Last Updated: 2025-09-29 Source Code: https://bitbucket.org/i2cinc/i2c.salesforce.metadata/src/STAGING/force-app/main/default/lwc/reCaptcha

API Name: c-reCaptcha Type: Utility Component Target: Not exposed

Business Purpose

Integrates Google reCAPTCHA v2 (checkbox "I'm not a robot") into Salesforce forms to prevent spam and bot submissions. The component handles reCAPTCHA rendering, verification with Salesforce backend, responsive scaling, and lifecycle management.

User Interface

Visual Description

  • Layout: Google reCAPTCHA badge (302x78px base size)
  • Key UI Elements: Checkbox "I'm not a robot", badge image
  • Responsive: Scales down on smaller screens using CSS transform

Component Structure

Files

  • reCaptcha.html - Template with div container
  • reCaptcha.js - Controller (82 lines)
  • reCaptcha.js-meta.xml - Not exposed

JavaScript Controller

Properties

No @api properties

Event Handlers

grecaptchaVerified (document event)

  • Calls ReCaptchaController.insertRecord with response token
  • Dispatches "checked" event on success
  • Console logs errors

grecaptchaExpired (document event)

  • Dispatches "expired" event

window resize

  • Calls applyScale() to maintain responsive sizing

Private Methods

applyScale()

Purpose: Dynamically scales reCAPTCHA to fit container using CSS transform Called By: renderedCallback, window resize event

renderedCallback()

Purpose: Renders reCAPTCHA using grecaptcha.render() via custom event Polling: Uses setInterval(100ms) to wait for grecaptcha global

Lifecycle

connectedCallback()

  • Registers document event listeners (grecaptchaVerified, grecaptchaExpired)
  • Registers window resize listener

disconnectedCallback()

  • Removes window resize listener

Events

Events Dispatched

checked

  • Fired when reCAPTCHA verification succeeds
  • No detail payload

expired

  • Fired when reCAPTCHA token expires
  • No detail payload

Document Events Listened

grecaptchaRender

  • Dispatched by component to trigger rendering
  • Detail: { element, badge: "bottomright", size: "compact" }

grecaptchaVerified

  • Dispatched by reCAPTCHA script after user verification
  • Detail: { response: token }

grecaptchaExpired

  • Dispatched when reCAPTCHA expires

Dependencies

Apex Classes

  • ReCaptchaController.insertRecord(): Verifies reCAPTCHA response with Google

External Scripts

  • Google reCAPTCHA v2 script (loaded externally)
  • Global grecaptcha object

Configuration

Not exposed - embedded component

Usage Examples

<c-re-captcha
    onchecked={handleCaptchaChecked}
    onexpired={handleCaptchaExpired}>
</c-re-captcha>

⚠️ Pre-Go-Live Concerns

CRITICAL - Fix Before Go-Live

  • Polling with setInterval: Lines 40-51 poll every 100ms indefinitely until grecaptcha loads - should have timeout
  • No cleanup of setInterval: If component unmounts before grecaptcha loads, interval leaks

HIGH - Address Soon After Go-Live

  • No unit tests: Zero coverage
  • Console.error in production: Line 19
  • No loading state: User sees blank space while polling
  • Hardcoded compact size: May not suit all form layouts
  • Direct DOM manipulation: Uses getBoundingClientRect (could use ResizeObserver)

MEDIUM - Future Enhancement

  • Add invisible reCAPTCHA option: Support invisible mode
  • Make size configurable: Allow normal/compact via @api

Maintenance Notes

Complexity: Medium Recommended Review Schedule: Annually

Key Notes: - Requires external reCAPTCHA script to be loaded first - Polling interval could fail if script never loads (add timeout) - Responsive scaling uses CSS transform - works well but unusual approach - Event names use document-level custom events (not standard LWC pattern) - Component manages Google reCAPTCHA lifecycle

Browser Compatibility: - Chrome: Latest - Firefox: Latest - Safari: Latest - Mobile: iOS 12+, Android 8+ (reCAPTCHA supported)