Skip to main content
This guide walks through the process of implementing Perch embeddable tools on various Content Management Systems (CMS) and technical platforms.

Basic embed code structure

All Perch widgets use the same simple two-line integration. The widget ID will either be provided by your Perch representative (for custom configurations) or you can use one of the predefined static widget IDs for Lead Management:
<!-- DIV PORTION -->
<div class="perch-widget" widget-id="your-widget-id">
    <div class="perch-widget-loading-indicator">Loading...</div>
</div>

<!-- SCRIPT PORTION -->
<script src="https://embeds.myperch.io/assets/perch-embed-widget.js"></script>
Widget ID Options:
  • Custom widgets: Your Perch representative provides a specific widget ID (e.g., ABC123)
  • Static Lead Management widgets: Use predefined IDs following static-{portal}-{parent} format (see Widget Embedding for all available IDs)
The Perch widget script is only 1KB in size, ensuring minimal impact on your page load performance.

Custom loading indicator

To improve the client user experience, we’ve added a feature to provide a custom loading indicator. You can use the inner <div> with the class .perch-widget-loading-indicator to insert a plain text loader (e.g. ‘Loading…’) that will be visible while the tool is being downloaded and rendered. You can replace the contents of this <div> with a custom message or a loading indicator of your choice to better match your branding:
<div class="perch-widget" widget-id="YOUR-WIDGET-ID">
    <div class="perch-widget-loading-indicator">
        <span>Loading mortgage calculator...</span>
        <!-- Or add your own custom loading animation -->
    </div>
</div>
Be sure that you retain the .perch-widget-loading-indicator class as this is what our script looks for when removing the loading indicator upon successful initialization of your widget.

CMS-specific instructions

Important: In most cases, the CMS editor will not execute JavaScript and therefore the tool will not render in the editor. Instead you will see the “Loading…” text. To view the rendered tool, select your CMS’s “preview” option to see the live version.

WordPress + Elementor

  1. Navigate to the page where you want to embed the tool within your editor
  2. Add a new HTML element using Elementor
  3. Paste the provided <div> and <script> tags into the HTML element
  4. Save and publish your changes

Webflow

  1. Go to the page you wish to embed the tool on
  2. Add an Embed element to your page
  3. Paste the provided <div> and <script> tags into the Embed element
  4. Publish your site to see the tool in action

Squarespace

  1. Go to the page where you want to embed the tool
  2. Click on the + icon to add a new block and select Code
  3. Paste the provided <div> and <script> tags into the Code block
  4. Apply and save your changes

KVCore

KVCore is different from other website CMS in that you need to enter the <div> and <script> tags in different locations:
  1. Add the script tag:
    • Hover over Web & IDX in your sidebar navigation to reveal the menu
    • Select Website Settings to open your website’s setting panel
    • Scroll down to the custom header section
    • Put your <script> tag in this box and hit save
  2. Add the div portion:
    • Go into your custom page editor
    • Click the embed option <>
    • Paste the <div> portion of your tool into the box
    • Hit save and apply your changes to the site

Single Page Application integration

Perch Widgets can be easily integrated into single-page applications (SPAs) like Angular, Vue.js, or React. However, SPAs manage the DOM differently compared to traditional multi-page websites.

Why manual initialization is needed

In a traditional setup, the widget script relies on the DOM ready event to initialize. But in SPAs, the DOM is often dynamically updated, and elements containing the widget may not be available at the traditional DOM ready event. To support dynamic rendering in SPAs, we’ve added a custom event emitter that allows you to manually trigger widget initialization whenever your components mount.

Steps to initialize a widget in an SPA

  1. Load the Perch widget script - Choose one of two approaches:
    • Static approach: Add the script tag to your main HTML file (e.g., index.html)
    • Dynamic approach: Load the script programmatically in your component code
  2. Insert the widget div into your HTML where you want it to appear
  3. Listen for the appropriate lifecycle hook in your framework that guarantees the element containing the widget is present in the DOM
  4. Emit the Perch widget initialization event once the widget’s DOM element is available

Basic examples

Add the script tag to your main HTML file. This ensures the script is available immediately:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Your App</title>
  <script src="https://embeds.myperch.io/assets/perch-embed-widget.js"></script>
</head>
<body>
  <div id="root"></div>
</body>
</html>
Add the widget div where you want it to appear:
<div class="perch-widget" widget-id="your-widget-id">
  <div class="perch-widget-loading-indicator">Loading...</div>
</div>
When using this approach, your initialization function only needs to emit the event:
function initializePerchWidget(widgetId) {
  const event = new CustomEvent('perch-widget:init', {
    detail: {
      perchWidgetId: widgetId
    }
  });
  window.dispatchEvent(event);
}

// Call this after the widget div is added to the page
initializePerchWidget('your-widget-id');

Framework examples

The following examples demonstrate both approaches. Each example uses the dynamic loading approach, but you can simplify the code by using static loading instead (just add the script to your HTML and remove the script loading logic).

Angular example

widget-container.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-widget-container',
  template: `<div class="perch-widget" widget-id="abc123">
    <div class="perch-widget-loading-indicator">Loading...</div>
  </div>`,
})
export class WidgetContainerComponent implements OnInit {

  ngOnInit() {
    this.initializePerchWidget('abc123');
  }

  private initializePerchWidget(widgetId: string): void {
    // Helper function to emit the initialization event
    const emitInitEvent = () => {
      const event = new CustomEvent('perch-widget:init', {
        detail: {
          perchWidgetId: widgetId
        }
      });
      window.dispatchEvent(event);
    };
    
    // Check if script is already loaded
    const existingScript = document.querySelector('script[src*="perch-embed-widget.js"]');
    
    if (existingScript) {
      // Script already exists, just emit the initialization event
      emitInitEvent();
      return;
    }
    
    // Create and append the script tag
    const script = document.createElement('script');
    script.src = 'https://embeds.myperch.io/assets/perch-embed-widget.js';
    script.async = true;
    
    // Initialize widget once script loads
    script.onload = emitInitEvent;
    
    // Append script to document head
    document.head.appendChild(script);
  }
}

Vue.js example

WidgetContainer.vue
<template>
  <div class="perch-widget" widget-id="abc123">
    <div class="perch-widget-loading-indicator">Loading...</div>
  </div>
</template>

<script>
export default {
  mounted() {
    this.initializePerchWidget('abc123');
  },
  methods: {
    initializePerchWidget(widgetId) {
      // Helper function to emit the initialization event
      const emitInitEvent = () => {
        const event = new CustomEvent('perch-widget:init', {
          detail: {
            perchWidgetId: widgetId
          }
        });
        window.dispatchEvent(event);
      };
      
      // Check if script is already loaded
      const existingScript = document.querySelector('script[src*="perch-embed-widget.js"]');
      
      if (existingScript) {
        // Script already exists, just emit the initialization event
        emitInitEvent();
        return;
      }
      
      // Create and append the script tag
      const script = document.createElement('script');
      script.src = 'https://embeds.myperch.io/assets/perch-embed-widget.js';
      script.async = true;
      
      // Initialize widget once script loads
      script.onload = emitInitEvent;
      
      // Append script to document head
      document.head.appendChild(script);
    }
  }
}
</script>

React example

WidgetContainer.jsx
import { useEffect } from 'react';

function WidgetContainer() {
  useEffect(() => {
    initializePerchWidget('abc123');
  }, []);

  const initializePerchWidget = (widgetId) => {
    // Helper function to emit the initialization event
    const emitInitEvent = () => {
      const event = new CustomEvent('perch-widget:init', {
        detail: {
          perchWidgetId: widgetId
        }
      });
      window.dispatchEvent(event);
    };
    
    // Check if script is already loaded
    const existingScript = document.querySelector('script[src*="perch-embed-widget.js"]');
    
    if (existingScript) {
      // Script already exists, just emit the initialization event
      emitInitEvent();
      return;
    }
    
    // Create and append the script tag
    const script = document.createElement('script');
    script.src = 'https://embeds.myperch.io/assets/perch-embed-widget.js';
    script.async = true;
    
    // Initialize widget once script loads
    script.onload = emitInitEvent;
    
    // Append script to document head
    document.head.appendChild(script);
  };

  return (
    <div className="perch-widget" widget-id="abc123">
      <div className="perch-widget-loading-indicator">Loading...</div>
    </div>
  );
}

export default WidgetContainer;

Best practices for SPAs

  • Load the script only once - The initialization function includes checks to prevent loading the script multiple times, which is important for performance and avoiding conflicts
  • Ensure that each widget is initialized only once per page, particularly in SPAs where pages may not fully reload
  • Dispatch the event at the earliest point where you can guarantee the DOM element for the widget is present
  • Clean up properly when components are unmounted to prevent memory leaks

Custom implementations

For custom implementations or unique technical requirements, refer to the Basic examples section above for the complete initialization function. Choose either the static or dynamic loading approach based on your needs.

Troubleshooting

Widget not appearing

  • Ensure the script tag is included on the page
  • Check that the widget ID matches what was provided by Perch
  • Verify JavaScript is enabled and not being blocked

Widget shows “Loading…” indefinitely

  • Check browser console for JavaScript errors
  • Ensure the page is being viewed live (not in editor mode)
  • Verify the script URL is accessible

Multiple widgets on one page

  • Each widget should have a unique widget-id
  • The script only needs to be included once per page
  • All widgets will initialize automatically