Skip to main content

Documentation Index

Fetch the complete documentation index at: https://partner-integrations.voyado.com/llms.txt

Use this file to discover all available pages before exploring further.

When adding custom functionality to this extension, make sure to create your own plugin. Otherwise, you may interfere with the existing code and risk breaking it.

How to add custom attributes to the Contact

To store custom attributes for a contact in Engage, these plugins can be used:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
	<type name="Voyado\Magento2\Helper\ContactAttributesHelper">
		<plugin name="Voyado_ExtendedVoyado_Plugin_Sdk_To_Voyado" type="Voyado\ExtendedVoyado\Plugin\Sdk\ToVoyado"/>
	</type>
</config>
<?php
namespace Voyado\ExtendedVoyado\Plugin\Sdk;

use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Model\Customer;
use Voyado\Magento2\Helper\ContactAttributesHelper as VoyadoContactAttributesHelper;

class ToVoyado
{
    /**
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function afterGetRequiredFieldsCustomer(
        VoyadoContactAttributesHelper $object,
        array $requiredFieldsCustomer
    ): array {
        return array_merge($requiredFieldsCustomer, ['married', 'region']);
    }

    /**
     * @param CustomerInterface|Customer $customer
     * @return \Swagger\Client\model\ContactAttributes
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function afterGetContactAttributeDataFromCustomer(
        VoyadoContactAttributesHelper $object,
        array $result,
        $customer
    ): array {
        $extraData = [
            'married' => 'MarriedExtraPropertyDummyValue',
            'region' => 'RegionExtraPropertyDummyValue',
        ];
        return array_merge($result, $extraData);
    }
}

How to add custom data to the Order

This guide walks you through adding custom key-value pairs to the extra_data field in the api/v2/orders payload sent to Voyado. You do this with a Magento after-plugin — no modification to the Voyado extension source is needed.

Before you start

  • You need a working Voyado Adobe Commerce integration.
  • All customizations must live in a separate Adobe Commerce module that depends on Voyado_Magento2. Do not edit the extension’s files directly — your changes would be overwritten on the next Composer update.

How extra data works

Every order exported to api/v2/orders includes an extra_data object. This is a flat string-to-string map — both keys and values must be strings. The extension populates it by default with shipping, billing, and payment details. The extension calls getExtraDataForOrder() in Voyado\Magento2\Helper\VoyadoHelper to build this map. You extend it with an afterGetExtraDataForOrder plugin that receives the existing array and returns it with your additions.
The Voyado API model types extra_data as map[string,string]. All values must be strings. If you pass a nested array or object, the serializer will cast it to the string "Array", which is not what you want. To include structured data, JSON-encode it into a string value as shown below.

How to create the module

Create app/code/VendorName/ExtendedVoyado/registration.php:
<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'VendorName_ExtendedVoyado',
    __DIR__
);
Replace VendorName with your own vendor name throughout this guide.
Create app/code/VendorName/ExtendedVoyado/etc/module.xml:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="VendorName_ExtendedVoyado">
        <sequence>
            <module name="Voyado_Magento2" />
        </sequence>
    </module>
</config>
Create app/code/VendorName/ExtendedVoyado/etc/di.xml:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Voyado\Magento2\Helper\VoyadoHelper">
        <plugin name="VendorName_ExtendedVoyado_Plugin_AddExtraOrderData"
                type="VendorName\ExtendedVoyado\Plugin\AddExtraOrderData" />
    </type>
</config>
Create app/code/VendorName/ExtendedVoyado/Plugin/AddExtraOrderData.php.The plugin receives the existing extra_data array in $result — which already contains all the default fields like shipping address, billing address, and payment method. You add your field to this array and return it. Nothing else in the payload is affected.In this example, we read a custom order field called discount_code and add it as discountCode in the extraData object:
<?php
declare(strict_types=1);

namespace VendorName\ExtendedVoyado\Plugin;

use Voyado\Magento2\Helper\VoyadoHelper;

class AddExtraOrderData
{
    public function afterGetExtraDataForOrder(
        VoyadoHelper $subject,
        array $result,
        $order
    ): array {
        $discountCode = $order->getData('discount_code');

        if (!empty($discountCode)) {
            $result['discountCode'] = (string) $discountCode;
        }

        return $result;
    }
}
After this plugin runs, the extraData object in the api/v2/orders payload will contain your new field alongside all the existing fields:
{
  "extraData": {
    "shipping_method": "DHL",
    "shipping_amount": "49.00",
    "customer_firstname": "John",
    "customer_lastname": "Doe",
    "billing_street": "Example Avenue 12",
    "billing_zipcode": "123 45",
    "billing_city": "Examplecity",
    "billing_country": "SE",
    "payment_method": "Kort",
    "discountCode": "WELCOME10"
  }
}
The $result parameter contains the full existing extra_data array built by the extension. By adding a key and returning the array, your field is merged into the same object. You are not creating a new object — you are extending the one that already exists.
All values in extra_data must be strings. The Voyado API model types this field as map[string,string]. If you pass a non-string value (e.g. an integer or array), cast it with (string) or use json_encode() for complex types.
Run the standard Magento setup commands:
bin/magento module:enable VendorName_ExtendedVoyado
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
Then place a test order and check the voyado_magento2_status table. Look at the request column for the order export — your new fields should appear in the extraData object of the JSON body.
The extension populates these fields by default. Your plugin adds to this — it does not replace it.
KeySource
website_codeStore ID
shipping_methodOrder shipping description
shipping_descriptionOrder shipping description
shipping_amountBase shipping amount including tax
customer_firstname, customer_middlename, customer_lastnameBilling address
customer_telephonenumberBilling address telephone
billing_company, billing_street, billing_zipcode, billing_city, billing_countryBilling address
shipping_firstname, shipping_middlename, shipping_lastnameShipping address
shipping_telephonenumber, shipping_company, shipping_street, shipping_zipcode, shipping_city, shipping_countryShipping address
payment_methodPayment method config value
shipping_track or shipping_track_number + shipping_track_urlShipment tracking (depending on config)
Do not overwrite any of these default keys unless you specifically intend to replace their values. Your plugin receives the full existing array in $result — add to it, do not reassign it.

Common mistakes

MistakeWhat happensFix
Passing an array as a value instead of a stringThe value is serialized as "Array" in the API requestUse json_encode() to convert the array to a string
Reassigning $result to a new arrayAll default extra_data fields are lostAlways add keys to the existing $result and return it
Forgetting (string) cast on non-string dataInteger or float values may cause type mismatchesCast all values to string, or use json_encode() for complex types
Editing the Voyado extension source directlyChanges are lost on the next composer updateAlways use a separate module with a plugin as shown above