# Send data from TYPO3 Form to Hubspot Form
## 1. Create hubspotFinisher:
#### 1.1 Add `HubspotFinisher.php`
- `RouteToExtension/Classes/Domain/Finishers/HubspotFinisher.php`
```php
<?php
namespace YourDomain\Finishers;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher;
class HubspotFinisher extends AbstractFinisher
{
}
```
#### 1.2 Add `HubspotFinisher.yaml`
- `RouteToExtension/Configuration/Yaml/Form/Finisher/HubspotFinisher.yaml`
```yaml
TYPO3:
CMS:
Form:
prototypes:
standard:
finishersDefinition:
Hubspot:
formEditor:
iconIdentifier: 't3-form-icon-finisher'
predefinedDefaults:
options:
removeAfter: '0'
implementationClassName: 'YourDomain\Finishers\HubspotFinisher'
options:
```
## 2. Know Hubspot rules
https://legacydocs.hubspot.com/docs/methods/forms/submit_form_v3_authentication
```json
{
"submittedAt": "1517927174000", // This millisecond timestamp is optional. Update the value from "1517927174000" to avoid an INVALID_TIMESTAMP error.
"fields": [
{
"objectTypeId": "0-1",
"name": "email",
"value": "example@example.com"
},
{
"objectTypeId": "0-1",
"name": "firstname",
"value": "Jeff"
}
],
"context": {
"hutk": ":hutk", // include this parameter and set it to the hubspotutk cookie value to enable cookie tracking on your submission
"pageUri": "www.example.com/page",
"pageName": "Example page"
},
"legalConsentOptions": {
"consent": { // Include this object when GDPR options are enabled
"consentToProcess": true,
"text": "I agree to allow Example Company to store and process my personal data.",
"communications": [
{
"value": true,
"subscriptionTypeId": 999,
"text": "I agree to receive marketing communications from Example Company."
}
]
}
}
}
```
## 3. Collect TYPO3 form data and put it into Hubspot data
```php
$formvalues = $this->finisherContext->getFormValues();
$definition = $this->finisherContext->getFormRuntime()->getFormDefinition()->getElements();
$HubspotFormId = $this->parseOption('HubspotFormId');
```
```php
$hubspotData = [];
$hubspotNamesList = ['firstname','lastname','email','company','jobtitle','phone','country',...];
# this step collects data from TYPO3 form and put it into hubspotData array
foreach ($definition as $element) {
if (empty($element->getProperties()['hubspotName'])) {
$logger->warning('Element ' . $element->getIdentifier() . ' in form '. $this->finisherContext- >getFormRuntime()->getIdentifier() . ' has no Hubspot field name set. This might cause API Errors or data loss.');
}
if (in_array($element->getProperties()['hubspotName'],$hubspotNamesList)) {
// The array $hubspotData contains the info that we will send to Hubspot
// the index in the array are the names of the properties in the form
// for example: $hubspotData['email'] has the value ...@pagemachine.de
$hubspotData[$element->getProperties()['hubspotName']] = $values[$element->getIdentifier()];
}
}
```
## 4. Process Hubspot data:
- Turn `$hubspotData` into `$requestBody`
```php
$requestBody = [
'fields' => [],
];
$field = [];
foreach ($hubspotData as $field_key=>$field_value) {
$field['objectTypeId'] = '0-1';
$field['name'] = $field_key;
$field['value'] = $field_value;
array_push($requestBody['fields'], $field);
}
```
- Turn `$requestBody` into **json** `$encodedBody`
```php
$encodedBody=json_encode($requestBody);
```
## 5. Send processed Hubspot data via `https` request
```php
# get $authToken $portalId and $formId
$authToken=$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['f7forms']['hubspot_OAuth_token'];
$portalId=$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['f7forms']['hubspot_portalId'];
$formId=$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['f7forms']['hubspot_formId'];
# create request
$requestFactory=GeneralUtility::makeInstance(RequestFactory::class);
$authorization = 'Bearer ' . $authToken;
$url = 'https://api.hsforms.com/submissions/v3/integration/secure/submit/';
$url = $url . $portalId . '/' . $formId;
# send request
$response=$requestFactory->request($url,'POST',['headers' =>['Content-Type'=>'application/json', 'Authorization'=>$authorization], 'body'=>$encodedBody]);
# check response
if($response->getStatusCode()===200){
return $response->getBody()->getContents();
}
if($response->getStatusCode()===602){
return false;
}
```