{"id":13119,"date":"2026-06-22T11:00:00","date_gmt":"2026-06-22T10:00:00","guid":{"rendered":"https:\/\/www.bronco.co.uk\/our-ideas\/?p=13119"},"modified":"2026-06-19T11:37:46","modified_gmt":"2026-06-19T10:37:46","slug":"how-to-sync-website-users-to-hubspot-using-php","status":"publish","type":"post","link":"https:\/\/www.bronco.co.uk\/our-ideas\/how-to-sync-website-users-to-hubspot-using-php\/","title":{"rendered":"How to Sync Website Users to HubSpot Using PHP"},"content":{"rendered":"\n<p>Integrating your website directly with HubSpot allows you to automatically sync user data without relying on manual exports or third-party form tools.<\/p>\n\n\n\n<p>This is especially useful for membership sites, SaaS platforms, and any application where users register and update their details directly on your system.<\/p>\n\n\n\n<p>In this guide, we\u2019ll build a simple PHP integration using the official HubSpot SDK that will allow you to create, update, and manage contacts automatically.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Install the HubSpot SDK<\/h2>\n\n\n\n<p>Install the official HubSpot PHP SDK using Composer:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>composer require hubspot\/api-client<\/code><\/pre><\/div>\n\n\n\n<p>Then include Composer\u2019s autoloader in your project:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>require_once &#39;vendor\/autoload.php&#39;;<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Create a HubSpot Private App<\/h2>\n\n\n\n<p>To connect your application to HubSpot, you need an access token from a Private App.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Go to HubSpot settings<\/li>\n\n\n\n<li>Navigate to Integrations \u2192 Private Apps<\/li>\n\n\n\n<li>Create a new app<\/li>\n\n\n\n<li>Enable CRM Contacts read\/write access<\/li>\n\n\n\n<li>Copy your access token<\/li>\n<\/ul>\n\n\n\n<p>Store your token securely using an environment variable:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>$accessToken = getenv(&#39;HUBSPOT_ACCESS_TOKEN&#39;);<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Create the HubSpot Class<\/h2>\n\n\n\n<p>Create a simple service class to initialise the HubSpot client.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>&lt;?php\n\nuse HubSpot\\Factory;\nuse HubSpot\\Client\\Crm\\Contacts\\Model\\Filter;\nuse HubSpot\\Client\\Crm\\Contacts\\Model\\FilterGroup;\nuse HubSpot\\Client\\Crm\\Contacts\\Model\\PublicObjectSearchRequest;\nuse HubSpot\\Client\\Crm\\Contacts\\Model\\SimplePublicObjectInput;\n\nclass Hubspot\n{\n    private $client;\n\n    public function __construct()\n    {\n        $this-&gt;client = Factory::createWithAccessToken(\n            getenv(&#39;HUBSPOT_ACCESS_TOKEN&#39;)\n        );\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Map User Data to HubSpot Properties<\/h2>\n\n\n\n<p>Before sending data to HubSpot, map your user object to HubSpot&#8217;s contact properties. Also include any custom properties you may have created within Hubspot. <\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>public function assignUserProperties($user)\n{\n    if (!$user-&gt;userid) {\n        return false;\n    }\n\n    return [\n        &#39;user_id&#39; =&gt; $user-&gt;userid,\n        &#39;email&#39; =&gt; $user-&gt;email,\n        &#39;phone&#39; =&gt; $user-&gt;tel_code . $user-&gt;tel,\n        &#39;firstname&#39; =&gt; $user-&gt;fname,\n        &#39;lastname&#39; =&gt; $user-&gt;lname,\n        &#39;subscribed&#39; =&gt; $user-&gt;subscribed,\n        &#39;subscription_start_date&#39; =&gt; $user-&gt;sub_start,\n        &#39;subscription_expiry_date&#39; =&gt; $user-&gt;sub_expire,\n        &#39;last_login&#39; =&gt; $user-&gt;last_login,\n    ];\n}<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Check for Existing Contacts<\/h2>\n\n\n\n<p>Check whether the email already exists in HubSpot to avoid duplicates.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>public function searchContacts($property, $value)\n{\n    $filter = new Filter([\n        &#39;property_name&#39; =&gt; $property,\n        &#39;operator&#39; =&gt; &#39;EQ&#39;,\n        &#39;value&#39; =&gt; $value\n    ]);\n\n    $filterGroup = new FilterGroup([\n        &#39;filters&#39; =&gt; [$filter]\n    ]);\n\n    $searchRequest = new PublicObjectSearchRequest([\n        &#39;filter_groups&#39; =&gt; [$filterGroup],\n        &#39;limit&#39; =&gt; 1\n    ]);\n\n    $results = $this-&gt;client\n        -&gt;crm()\n        -&gt;contacts()\n        -&gt;searchApi()\n        -&gt;doSearch($searchRequest);\n\n    if (count($results-&gt;getResults()) &gt; 0) {\n        return $results-&gt;getResults()[0]-&gt;getId();\n    }\n\n    return false;\n}<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6: Create a Contact<\/h2>\n\n\n\n<p>Create a new one in HubSpot (automatically check for duplicates).<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>public function addContact($user)\n{\n    $existingId = $this-&gt;searchContacts(&#39;email&#39;, $user-&gt;email);\n\n    if ($existingId) {\n        \/\/ UPDATE DATABASE; contact already exists in Hubspot, update `hubspot_contactid` in user table with $existingId\n\n        return true;\n    }\n\n    $contact = new SimplePublicObjectInput([\n        &#39;properties&#39; =&gt; $this-&gt;assignUserProperties($user)\n    ]);\n\n    try {\n        $response = $this-&gt;client\n            -&gt;crm()\n            -&gt;contacts()\n            -&gt;basicApi()\n            -&gt;create($contact);\n\n        $hubspotId = $response-&gt;getId();\n\n        \/\/ You need to store the $hubspotId in your database here\n\n        return true;\n\n    } catch (Exception $e) {\n        return false;\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Step 7: Update a Contact<\/h2>\n\n\n\n<p>When a user updates their account, we push the changes to HubSpot. If the user doesn&#8217;t already have a <code>hubspot_contactid<\/code> add a new contact instead.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>public function updateContact($user)\n{\n    if (!$user-&gt;hubspot_contactid) {\n        return $this-&gt;addContact($user);\n    }\n\n    $contact = new SimplePublicObjectInput([\n        &#39;properties&#39; =&gt; $this-&gt;assignUserProperties($user)\n    ]);\n\n    try {\n        $this-&gt;client\n            -&gt;crm()\n            -&gt;contacts()\n            -&gt;basicApi()\n            -&gt;update(\n                $user-&gt;hubspot_contactid,\n                $contact\n            );\n\n        \/\/ UPDATE DATABASE; I recommend having a `hubspot_last_updated` field to update in the users table, or some sort of log so you can track what&#39;s going on\n\n        return true;\n\n    } catch (Exception $e) {\n        return false;\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8: Delete a Contact<\/h2>\n\n\n\n<p>You can also archive contacts in HubSpot if needed i.e. when admin or the user themselves deletes a user account. <\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>public function deleteContact($contactId)\n{\n    if (!$contactId) {\n        return false;\n    }\n\n    try {\n        $this-&gt;client\n            -&gt;crm()\n            -&gt;contacts()\n            -&gt;basicApi()\n            -&gt;archive($contactId);\n\n        return true;\n\n    } catch (Exception $e) {\n        return false;\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p>Note that in the try\/catch blocks you&#8217;ll want to deal with and log errors properly. <\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>This code is free to use at your own discretion. It comes without warranty. Please feel free to feedback any edits.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Integrating your website directly with HubSpot allows you to automatically sync user data without relying on manual exports or third-party form tools. This is especially useful for membership sites, SaaS platforms, and any application where users register and update their details directly on your system. In this guide, we\u2019ll build a simple PHP integration using [&hellip;]<\/p>\n","protected":false},"author":12,"featured_media":13135,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"class_list":["post-13119","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-and-ux"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/posts\/13119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/comments?post=13119"}],"version-history":[{"count":10,"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/posts\/13119\/revisions"}],"predecessor-version":[{"id":13134,"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/posts\/13119\/revisions\/13134"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/media\/13135"}],"wp:attachment":[{"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/media?parent=13119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bronco.co.uk\/our-ideas\/wp-json\/wp\/v2\/categories?post=13119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}