Adding Hum to Your Application

The Hum widget provides a seamless way to integrate internet service provider discovery into your website or application. With just a few lines of code, you can add a fully functional home internet service e-commerce experience that provides your users with address-specific plans, pricing, and service ordering capabilities.
Hum widget checkout layout showing the complete e-commerce flow

Architecture

The Hum widget is built as a React single-page application using client-side rendering. It’s fully responsive and adapts smoothly to desktop, tablet, and mobile devices.
The widget loads asynchronously and won’t block your page’s initial render performance.

Installation

Follow these steps to integrate the Hum widget into your application:
1

Add the Widget Container

Add a container div with a specific ID where you want the widget to render:
<div id="hum-widget"></div>
You can customize the container ID, but make sure it matches the element you pass to the widget constructor.
2

Add the Widget Script

Include the Hum widget script in your HTML page:
<script src="https://cdn.letshum.com/widget.js"></script>
The script loads asynchronously and is hosted on a CDN for optimal performance.
3

Initialize the Widget

Initialize the Hum widget instance with your API key and container element:
const hum = new HUM(
    'YOUR_API_KEY_HERE',
    document.getElementById('hum-widget'),
    {
        resultLayout: 'checkout', // or 'summary'
        campaignId: 'my_campaign_id' // optional campaign identifier
    }
);
hum.initialize();

// Store the instance globally for access by other page components
window.humInstance = hum;
Verify the widget loads by checking your browser’s developer console for any error messages.
The campaignId parameter is optional and allows you to track unique information about the user, session, or campaign. Use this for attribution of widget interactions to specific marketing campaigns or sources. Hum provides session information via monthly CSV reports that include the campaignId field for easy session and order attribution.

Widget Layout Options

The Hum widget supports two different layout modes that you can configure during initialization:
The checkout layout provides a fully responsive e-commerce experience, enabling your users to search, compare, and purchase internet service.Ideal for:
  • Use cases where users may actively be seeking new or lower-cost internet service
  • Dedicated pages within your app that can support the multi-step e-commerce experience
  • New tenant/homeowner apps, mortgage apps, consumer finance apps and more
Hum widget shopping cart layout showing plan comparison and selection
To specify the layout, use the resultLayout field during initialization:
const hum = new HUM(
    'YOUR_API_KEY_HERE',
    document.getElementById('hum-widget'),
    {
        resultLayout: 'summary', // or 'checkout'
        campaignId: 'my_campaign_id' // optional campaign identifier
    }
);
hum.initialize();
If you don’t specify a layout, the widget defaults to the checkout layout.

Address Data Format

The widget expects address data in a specific JSON format. Here’s the structure:
{
  "street1": "1001 Woodward Ave",        // Primary street address
  "street2": "Suite 500",                // Optional secondary address (apartment, suite, etc.)
  "city": "Detroit",                     // City name
  "state": "MI",                         // Two-letter state code
  "zip": "48226",                        // ZIP code
  "campaign_id": "Optional Campaign ID", // Optional tracking identifier
  "latitude": 42.3317,                   // Optional latitude coordinate
  "longitude": -83.0479                  // Optional longitude coordinate
}

Required Fields

street1
string
required
The primary street address. Should contain the street number and name.
city
string
required
The city name.
state
string
required
Two-letter state code (e.g., “MI” for Michigan).
zip
string
required
The ZIP code in 5 or 9-digit format.

Optional Fields

street2
string
Secondary address information such as apartment numbers, suite numbers, or additional address details.
campaign_id
string
Identifier for tracking purposes. Use this to associate widget interactions with specific marketing campaigns or sources. This campaign_id will be embedded in UTM parameters sent to the ISP and will be available in your Hum tracking.
latitude
number
Latitude coordinate for improved performance and reduced latency.
longitude
number
Longitude coordinate for improved performance and reduced latency.
Both latitude and longitude must be provided together. If only one is provided, the widget will return an error.

Integration Examples

Example 1: Form-Based Integration

This example shows how to integrate the widget with an HTML form for address input:
index.html
<!DOCTYPE html>
<html>
<head>
    <title>Hum Widget Demo</title>
    <script src="https://cdn.letshum.com/widget.js"></script>
</head>
<body>
    <!-- Widget container -->
    <div id="hum-widget"></div>

    <!-- Address input form -->
    <form id="address-search">
        <input type="text" name="street1" placeholder="Street Address" required>
        <input type="text" name="street2" placeholder="Apartment/Suite (Optional)">
        <input type="text" name="city" placeholder="City" required>
        <input type="text" name="state" placeholder="State (2 letters)" maxlength="2" required>
        <input type="text" name="zip" placeholder="ZIP Code" pattern="[0-9]{5}(-[0-9]{4})?" required>
        <input type="hidden" name="campaign_id" value="your-campaign-id">
        <button type="submit">Check Availability</button>
    </form>

    <script>
        // Initialize Hum widget with API key and container
        const hum = new HUM(
            'hum_live_1234567890abcdef', // Replace with your actual API key
            document.getElementById('hum-widget'),
            {
                resultLayout: 'checkout',
                campaignId: 'website-form-2024'
            }
        );
        
        // Initialize widget and handle errors
        hum.initialize()
            .then(() => {
                console.log('Hum widget initialized successfully');
            })
            .catch(error => {
                console.error('Failed to initialize Hum widget:', error);
                // Display user-friendly error message
                document.getElementById('hum-widget').innerHTML = 
                    '<p style="color: red;">Unable to load widget. Please try again later.</p>';
            });

        // Store the instance globally
        window.humInstance = hum;

        // Handle form submission with comprehensive error handling
        document.getElementById('address-search').addEventListener('submit', async (event) => {
            event.preventDefault();
            
            // Show loading state
            const submitButton = event.target.querySelector('button[type="submit"]');
            const originalText = submitButton.textContent;
            submitButton.textContent = 'Loading...';
            submitButton.disabled = true;
            
            try {
                // Get and validate form data
                const formData = new FormData(event.target);
                const addressData = Object.fromEntries(formData.entries());
                
                // Remove empty optional fields
                if (!addressData.street2) delete addressData.street2;
                if (!addressData.campaign_id) delete addressData.campaign_id;

                // Validate required fields
                if (!addressData.street1 || !addressData.city || !addressData.state || !addressData.zip) {
                    throw new Error('Please fill in all required fields');
                }

                // Submit address to widget
                const sessionToken = await hum.internetServiceFromAddress(addressData);
                console.log('Widget loaded with session token:', sessionToken);
                
            } catch (error) {
                console.error('Error loading internet service options:', error);
                
                // Display user-friendly error message
                alert('Unable to load internet service options. Please check your address and try again.');
                
            } finally {
                // Reset button state
                submitButton.textContent = originalText;
                submitButton.disabled = false;
            }
        });
    </script>
</body>
</html>
Test your integration by entering a valid US address and verifying that service options load correctly.

Example 2: Direct JSON Integration

This example shows how to pass address data directly as a JSON object:
direct-integration.html
<!DOCTYPE html>
<html>
<head>
    <title>Hum Widget Demo - Direct Integration</title>
    <script src="https://cdn.letshum.com/widget.js"></script>
</head>
<body>
    <!-- Widget container -->
    <div id="hum-widget"></div>

    <script>
        // Create a new instance of the HUM widget
        const hum = new HUM(
            'hum_live_1234567890abcdef', // Replace with your actual API key
            document.getElementById('hum-widget'),
            {
                resultLayout: 'summary', // Use summary layout for this example
                campaignId: 'direct-integration-2024'
            }
        );
        
        // Store the widget instance globally for access by other scripts
        window.humInstance = hum;

        // Address data in the required format
        const addressData = {
            street1: "1001 Woodward Ave",    // Primary street address (required)
            street2: "Suite 500",            // Secondary address info (optional)
            city: "Detroit",                 // City name (required)
            state: "MI",                     // Two-letter state code (required)
            zip: "48226",                    // ZIP code (required)
            campaign_id: "summer-2024",      // Optional tracking identifier
            latitude: 42.3317,               // Optional for better performance
            longitude: -83.0479              // Optional for better performance
        };

        // Initialize widget and load address data with proper error handling
        async function loadWidget() {
            try {
                // Initialize the widget first
                await hum.initialize();
                console.log('Hum widget initialized successfully');
                
                // Load internet service options for the address
                const sessionToken = await hum.internetServiceFromAddress(addressData);
                console.log('Internet service options loaded:', sessionToken);
                
            } catch (error) {
                console.error('Widget initialization or data loading failed:', error);
                
                // Display user-friendly error message
                const container = document.getElementById('hum-widget');
                container.innerHTML = `
                    <div style="padding: 20px; border: 1px solid #e74c3c; background: #fadbd8; color: #c0392b; border-radius: 4px;">
                        <h3>Unable to Load Internet Service Options</h3>
                        <p>We're having trouble loading service options for this address. Please try again later or contact support if the problem persists.</p>
                        <p><strong>Error:</strong> ${error.message}</p>
                    </div>
                `;
            }
        }

        // Load the widget when the page is ready
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', loadWidget);
        } else {
            loadWidget();
        }
    </script>
</body>
</html>
Use the direct integration approach when you already have address data available, such as from a previous form submission or user profile.

Address Validation

The widget uses the same address validation rules as the API:

Troubleshooting

If issues persist, check the browser console for detailed error messages and contact support with the specific error details.

Next Steps

Now that you have the Hum widget integrated, here are some recommended next steps:

Additional Resources