Documentation

Adding custom placeholders

Adding custom placeholders#

To add a custom placeholder to ShopMagic:

  1. Create a class that extends \WPDesk\ShopMagic\Workflow\Placeholder\Placeholder or an appropriate built-in base class.
  2. Register an instance through the shopmagic/core/placeholders filter.

This guide creates {{ order.nice_id }}, which returns text such as Your order id is: 11.

The example uses the API available in ShopMagic 4.9.3 and requires WooCommerce. Add the code in a separate custom plugin so that ShopMagic updates do not overwrite it.

How placeholder names work#

A placeholder’s full name combines its group and slug:

{{ group.slug }}

For {{ order.nice_id }}:

  • get_group_slug() returns order.
  • get_slug() returns nice_id, without the group name or braces.
  • get_name() combines them into order.nice_id.

Choose a unique combination of group and slug to avoid conflicts with existing placeholders.

Accessing event data#

ShopMagic passes event data to placeholders through \WPDesk\ShopMagic\Workflow\Event\DataLayer. The placeholder accesses this container through its protected $resources property.

Use has() to check whether a resource is available before retrieving it with get():

if ( $this->resources->has( \WC_Order::class ) ) {
    $order = $this->resources->get( \WC_Order::class );

    return (string) $order->get_id();
}

return '';

The selected event determines which resources are available. An order-based placeholder needs an event that provides a WC_Order object. Declaring a resource requirement does not load an order automatically.

Creating an order-based placeholder#

For placeholders that require order data, extend \WPDesk\ShopMagic\Workflow\Placeholder\Builtin\WooCommerceOrderBasedPlaceholder.

This base class provides:

  • The order group.
  • The WC_Order resource requirement.
  • The protected get_order() helper.

Your class must implement these methods:

  • get_slug(): string — the placeholder slug within its group.
  • get_description(): string — a description for the placeholder selector.
  • value( array $parameters ): string — the replacement value.

If you extend the general Placeholder class instead, also implement get_required_data_domains(): array. You can override get_group_slug(): string to define an explicit group.

Complete example: order.nice_id#

Create a folder named my-shopmagic-placeholders inside wp-content/plugins/. Add the following two files.

1. Create the placeholder class#

Save this code as class-nice-order-id.php:

<?php

namespace MyShopMagicPlaceholders;

use WPDesk\ShopMagic\Workflow\Placeholder\Builtin\WooCommerceOrderBasedPlaceholder;

final class NiceOrderId extends WooCommerceOrderBasedPlaceholder {

    public function get_slug(): string {
        return 'nice_id';
    }

    public function get_description(): string {
        return 'Display the order ID with a short message.';
    }

    public function value( array $parameters ): string {
        if ( ! $this->resources->has( \WC_Order::class ) ) {
            return '';
        }

        return sprintf(
            'Your order id is: %d',
            $this->get_order()->get_id()
        );
    }
}

2. Register the placeholder#

Save this code as my-shopmagic-placeholders.php in the same folder:

<?php
/**
 * Plugin Name: My ShopMagic Placeholders
 * Description: Custom order placeholders for ShopMagic.
 * Version: 1.0.0
 */

namespace MyShopMagicPlaceholders;

defined( 'ABSPATH' ) || exit;

add_filter(
    'shopmagic/core/placeholders',
    function ( array $placeholders ): array {
        require_once __DIR__ . '/class-nice-order-id.php';

        $placeholders[] = new NiceOrderId();

        return $placeholders;
    }
);

Activate My ShopMagic Placeholders under Plugins in WordPress. Keep ShopMagic and WooCommerce active.

The class file is loaded when ShopMagic requests the custom placeholders. This avoids extending the ShopMagic base class before it is available.

Append the new instance to the array and return the array. Do not replace it, as it may already contain placeholders registered by other integrations.

3. Use the placeholder#

Open an automation whose event provides order data and insert the following into a field that supports placeholders, such as the email message:

{{ order.nice_id }}

For an order with the internal ID 11, the result is:

Your order id is: 11

This example uses get_id(), which returns the internal WooCommerce order ID. If you need the displayed order number, use get_order_number() and change the sprintf() format from %d to %s.

Adding optional parameters#

The value() method receives placeholder parameters as an array of strings. For example:

{{ order.nice_id | prefix:'Order reference' }}

To support this parameter, replace the class’s value() method with:

public function value( array $parameters ): string {
    if ( ! $this->resources->has( \WC_Order::class ) ) {
        return '';
    }

    $prefix = $parameters['prefix'] ?? 'Your order id is';

    return sprintf(
        '%s: %d',
        $prefix,
        $this->get_order()->get_id()
    );
}

The result for order ID 11 is:

Order reference: 11

To expose the parameter in the placeholder selector, add this method to the class:

public function get_supported_parameters( $values = null ): array {
    return [
        ( new \WPDesk\ShopMagic\FormField\Field\InputTextField() )
            ->set_name( 'prefix' )
            ->set_label( 'Text before the order ID' ),
    ];
}

Parameter fields describe the options available in the selector. Your value() implementation still needs to handle missing or empty values as appropriate.

Fallback values and nested placeholders#

A parameter named fallback is not a global fallback mechanism. It works only when the placeholder’s value() method explicitly reads and uses it.

From ShopMagic 4.9.1, placeholder replacement values are not processed recursively. Do not return another placeholder shortcode from value() expecting ShopMagic to resolve it.

Nested placeholders inside parameter values are also unsupported. Read the required data directly from the event resources and return the final replacement string.

Testing your custom placeholder#

  1. Confirm that ShopMagic, WooCommerce, and your custom plugin are active.
  2. Open an automation with an event that provides order data.
  3. Insert {{ order.nice_id }} into a supported field.
  4. Trigger the event with a test order and check the resulting message.
  5. If you added a parameter, test both the default value and an explicitly supplied value.

If the result is empty, check that the custom plugin is active, the placeholder name matches the registered group and slug, and the event provides the required resource. Also check the action logs and PHP error log for relevant errors.

Not the solution you are looking for?

Please check other articles or open a support ticket.