• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » WordPress Development Recipe: Secure token-based API authentication for HubSpot Contacts in custom plugins

WordPress Development Recipe: Secure token-based API authentication for HubSpot Contacts in custom plugins

Prerequisites and Setup

This recipe assumes you have a working WordPress development environment and a basic understanding of PHP and WordPress plugin architecture. You’ll need a HubSpot account with API access enabled. Specifically, you’ll need to generate a HubSpot API Key. Navigate to your HubSpot account settings, then “Integrations” > “Private apps”. Create a new private app, grant it “Contacts” read access, and copy the generated API key. This key will be used to authenticate your requests.

For this example, we’ll create a simple WordPress plugin that fetches a list of contacts from HubSpot and displays their email addresses. We’ll store the HubSpot API key securely within WordPress options.

Storing the HubSpot API Key Securely

Never hardcode API keys directly into your plugin files. The recommended approach is to store sensitive credentials in the WordPress options database. We’ll create a settings page for the user to input their API key.

Plugin Structure

Create a new directory for your plugin, e.g., wp-content/plugins/hubspot-contacts-sync. Inside this directory, create the main plugin file, e.g., hubspot-contacts-sync.php.

Main Plugin File: hubspot-contacts-sync.php

This file will contain the plugin header, settings page registration, and the logic for saving the API key.

<?php
/**
 * Plugin Name: HubSpot Contacts Sync
 * Description: Fetches and displays HubSpot contacts using token-based authentication.
 * Version: 1.0
 * Author: Your Name
 * Author URI: https://yourwebsite.com
 */

// Prevent direct access to the file
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

// Add settings page to the admin menu
add_action( 'admin_menu', 'hcs_add_admin_menu' );
function hcs_add_admin_menu() {
    add_options_page(
        'HubSpot Contacts Sync Settings',
        'HubSpot Sync',
        'manage_options',
        'hubspot-contacts-sync',
        'hcs_options_page'
    );
}

// Render the settings page
function hcs_options_page() {
    ?>
    <div class="wrap">
        <h1>HubSpot Contacts Sync Settings</h1>
        <form method="post" action="options.php">
            
        </form>
    </div>
    Enter your HubSpot API Key below. Ensure it has "Contacts" read access.</p>';
}

function hcs_api_key_field_callback() {
    $api_key = get_option( 'hcs_hubspot_api_key' );
    ?>
    <input type="text" name="hcs_hubspot_api_key" value="" class="regular-text" />
    <p class="description">Get your API key from HubSpot <a href="https://app.hubspot.com/private-apps/api-key" target="_blank">here</a>.</p>
    


Making Authenticated API Requests

We'll use WordPress's built-in HTTP API to make requests to the HubSpot API. This is generally preferred over direct cURL calls as it handles many underlying complexities and security considerations.

HubSpot API Endpoint for Contacts

The endpoint for retrieving contacts is typically https://api.hubapi.com/contacts/v1/contacts/recent. Authentication is done via a query parameter named hapikey.

Function to Fetch Contacts

Add the following function to your hubspot-contacts-sync.php file. This function retrieves the API key, constructs the request URL, and uses wp_remote_get to fetch data.

/**
 * Fetches recent contacts from HubSpot.
 *
 * @return array|WP_Error An array of contacts or a WP_Error object on failure.
 */
function hcs_fetch_hubspot_contacts() {
    $api_key = hcs_get_hubspot_api_key();

    if ( empty( $api_key ) ) {
        return new WP_Error( 'api_key_missing', __( 'HubSpot API Key is not configured. Please set it in the plugin settings.', 'hubspot-contacts-sync' ) );
    }

    $api_url = 'https://api.hubapi.com/contacts/v1/contacts/recent';
    $request_url = add_query_arg( 'hapikey', $api_key, $api_url );

    $response = wp_remote_get( $request_url, array(
        'timeout' => 30, // Set a reasonable timeout
    ) );

    if ( is_wp_error( $response ) ) {
        return $response; // Return the WP_Error object
    }

    $response_code = wp_remote_retrieve_response_code( $response );
    $response_body = wp_remote_retrieve_body( $response );
    $data = json_decode( $response_body, true );

    if ( $response_code !== 200 ) {
        // Attempt to get an error message from HubSpot's response
        $error_message = isset( $data['message'] ) ? $data['message'] : 'Unknown error';
        return new WP_Error( 'hubspot_api_error', sprintf( __( 'HubSpot API Error (%d): %s', 'hubspot-contacts-sync' ), $response_code, $error_message ) );
    }

    // HubSpot API returns contacts in a 'contacts' array
    if ( isset( $data['contacts'] ) ) {
        return $data['contacts'];
    } else {
        return new WP_Error( 'hubspot_data_format_error', __( 'Unexpected response format from HubSpot API.', 'hubspot-contacts-sync' ) );
    }
}

Displaying Contacts on a WordPress Page

Now, let's create a shortcode that users can place on any WordPress page or post to display the fetched contacts. This involves calling our hcs_fetch_hubspot_contacts function and rendering the output.

Shortcode Implementation

Add the following shortcode function to your hubspot-contacts-sync.php file.

/**
 * Shortcode to display HubSpot contacts.
 * Usage: [hubspot_contacts]
 */
add_shortcode( 'hubspot_contacts', 'hcs_display_contacts_shortcode' );
function hcs_display_contacts_shortcode() {
    $contacts = hcs_fetch_hubspot_contacts();
    $output = '';

    if ( is_wp_error( $contacts ) ) {
        $output .= '<p style="color: red;">' . esc_html( $contacts->get_error_message() ) . '</p>';
    } elseif ( empty( $contacts ) ) {
        $output .= '<p>' . __( 'No contacts found or API key not configured.', 'hubspot-contacts-sync' ) . '</p>';
    } else {
        $output .= '<h3>' . __( 'HubSpot Contacts', 'hubspot-contacts-sync' ) . '</h3>';
        $output .= '<ul>';
        foreach ( $contacts as $contact ) {
            // HubSpot contact properties are nested
            $email = isset( $contact['properties']['email']['value'] ) ? $contact['properties']['email']['value'] : __( 'N/A', 'hubspot-contacts-sync' );
            $firstname = isset( $contact['properties']['firstname']['value'] ) ? $contact['properties']['firstname']['value'] : '';
            $lastname = isset( $contact['properties']['lastname']['value'] ) ? $contact['properties']['lastname']['value'] : '';

            $display_name = ! empty( $firstname ) || ! empty( $lastname ) ? trim( $firstname . ' ' . $lastname ) : $email;

            $output .= '<li>' . esc_html( $display_name ) . ' (' . esc_html( $email ) . ')</li>';
        }
        $output .= '</ul>';
    }

    return $output;
}

Activation and Usage

1. **Install the Plugin:** Upload the hubspot-contacts-sync folder to your wp-content/plugins/ directory or zip it and install via the WordPress admin. Activate the plugin from the "Plugins" page.

2. **Configure API Key:** Go to "Settings" > "HubSpot Sync" in your WordPress admin menu. Paste your HubSpot API Key into the provided field and click "Save Changes".

3. **Use the Shortcode:** Create or edit a WordPress page or post. Insert the shortcode [hubspot_contacts] where you want the list of contacts to appear. Save the page/post and view it on the front end.

Error Handling and Best Practices

The provided code includes basic error handling for missing API keys, network issues, and API-specific errors. For production environments, consider:

  • **More Robust Error Logging:** Instead of just displaying errors, log them to a file or the WordPress debug log for easier troubleshooting.
  • **Rate Limiting:** HubSpot has API rate limits. Implement checks or delays if you anticipate making a high volume of requests.
  • **Data Caching:** For performance, cache the fetched contact data for a reasonable period to avoid hitting the API on every page load. WordPress Transients API is ideal for this.
  • **Security:** While storing the API key in options is better than hardcoding, ensure your WordPress installation is secure. Consider using environment variables for API keys in more advanced setups, though this requires custom WordPress configuration.
  • **User Feedback:** Provide clear messages to the user if the API key is missing or if there are issues fetching data.
  • **Specific Property Fetching:** The HubSpot API allows you to request specific contact properties instead of all of them. This can improve performance and reduce data transfer. Modify the API call to include a `property` parameter if needed. For example: $request_url = add_query_arg( array( 'hapikey' => $api_key, 'property' => 'email,firstname,lastname' ), $api_url );

This recipe provides a solid foundation for integrating HubSpot contact data into your WordPress site securely and efficiently.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Reducing database query bloat in Sage Roots modern environments layouts using custom lazy loaders
  • Performance Optimization: Tuning PHP-FPM and opcache pools for high-concurrency Firebase Realtime DB handlers
  • Reducing Largest Contentful Paint (LCP) by optimizing custom script enqueuing structures in legacy plugins
  • How to implement native Redis caching layers for high-volume custom taxonomy queries in Carbon Fields custom wrappers
  • Building secure B2B pricing grids with custom REST API Controllers endpoints and role overrides

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (658)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (872)
  • PHP (5)
  • PHP Development (48)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (639)
  • SEO & Growth (492)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (182)
  • WordPress Plugin Development (197)
  • WordPress Plugin Development (330)
  • WordPress Theme Development (357)

Recent Posts

  • Reducing database query bloat in Sage Roots modern environments layouts using custom lazy loaders
  • Performance Optimization: Tuning PHP-FPM and opcache pools for high-concurrency Firebase Realtime DB handlers
  • Reducing Largest Contentful Paint (LCP) by optimizing custom script enqueuing structures in legacy plugins

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (872)
  • Debugging & Troubleshooting (658)
  • Security & Compliance (639)
  • SEO & Growth (492)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala