Deployment Upgrades – Automatically Activate ACSS, Frames, Etch and Etch Theme.

Tech Articles | 14 August 2026 | Blog, Bricks Builder, Coding, Etch, SureCart

Over the last couple of evenings, I have been making deployments easier. I’ve done this in an effort to make activation easier. I have been slowly building generic activation possibilities, having previously added Tasks-After-Install Freemius activation; I have now also added Surecart activation and written an activator to cover Frames and Automatic-CSS on bricks and etch installations.

This now means that ACF, Bricks, Etch, Etch Theme, ACSS, Frames, SureMail and CraftForms all automatically activate, and in the case of SureMail and Bricks, they also get set up with the base settings too.

This means my bundle installer can convert a site in record time from Etch to Bricks, etc.

ACSS / Frames

This has been achieved by adding the licence contact to Tasks after install and then having this snippet in my utility plugin

<?php
/**
 * Automatic.css + Frames Licence Activator
 *
 * Automatically activates:
 *
 * - Automatic.css 3.x
 *   define( 'AUTOMATIC_CSS_3_LICENSE_KEY', '...' );
 *
 * - Automatic.css 4.x
 *   define( 'AUTOMATIC_CSS_4_LICENSE_KEY', '...' );
 *
 * - Frames
 *   define( 'FRAMES_LICENSE_KEY', '...' );
 *
 * Once every installed/supported product is successfully licensed,
 * this snippet removes itself from:
 *
 * ninja_updater_selected_snippets
 */

defined( 'ABSPATH' ) || exit;


add_action( 'admin_init', function () {

	/*
	|--------------------------------------------------------------------------
	| Configuration
	|--------------------------------------------------------------------------
	*/

	$snippet_filename = 'Automatic-CSS-and-Frames-Activator.php';

	$completed_option = 'ninja_acss_frames_activator_completed';


	/*
	|--------------------------------------------------------------------------
	| Helper: remove this snippet from Ninja Updater
	|--------------------------------------------------------------------------
	*/

	$disable_self = static function () use ( $snippet_filename ) {

		$selected = get_option(
			'ninja_updater_selected_snippets',
			array()
		);

		if ( ! is_array( $selected ) ) {
			return;
		}

		$updated = array_values(
			array_filter(
				$selected,
				static function ( $filename ) use ( $snippet_filename ) {
					return (string) $filename !== $snippet_filename;
				}
			)
		);

		if ( $updated !== $selected ) {

			update_option(
				'ninja_updater_selected_snippets',
				$updated,
				false
			);
		}
	};


	/*
	|--------------------------------------------------------------------------
	| Helper: perform an EDD licence activation
	|--------------------------------------------------------------------------
	*/

	$activate_edd_license = static function (
		$store_url,
		$product_id,
		$product_name,
		$license,
		$key_option,
		$status_option
	) {

		$license = trim( (string) $license );

		if ( '' === $license ) {
			return false;
		}


		/*
		 * Already activated with this exact licence.
		 */
		$current_key = trim(
			(string) get_option( $key_option, '' )
		);

		$current_status = strtolower(
			trim(
				(string) get_option( $status_option, '' )
			)
		);

		if (
			hash_equals( $license, $current_key ) &&
			'valid' === $current_status
		) {
			return true;
		}


		/*
		 * Activate through the vendor's EDD endpoint.
		 */
		$response = wp_remote_post(
			$store_url,
			array(
				'timeout'   => 15,
				'sslverify' => true,
				'body'      => array(
					'edd_action'  => 'activate_license',
					'license'     => $license,
					'item_id'     => $product_id,
					'item_name'   => rawurlencode( $product_name ),
					'url'         => site_url(),
					'environment' => function_exists( 'wp_get_environment_type' )
						? wp_get_environment_type()
						: 'production',
				),
			)
		);


		if ( is_wp_error( $response ) ) {
			return false;
		}


		if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
			return false;
		}


		$data = json_decode(
			wp_remote_retrieve_body( $response )
		);


		if (
			! is_object( $data ) ||
			! isset( $data->success ) ||
			! isset( $data->license )
		) {
			return false;
		}


		/*
		 * EDD's successful activation should return:
		 *
		 * success = true
		 * license = valid
		 */
		if (
			true !== (bool) $data->success ||
			'valid' !== strtolower( (string) $data->license )
		) {
			return false;
		}


		/*
		 * Store the licence exactly where the plugin expects it.
		 */
		update_option(
			$key_option,
			$license,
			false
		);

		update_option(
			$status_option,
			(string) $data->license,
			false
		);


		return true;
	};


	/*
	|--------------------------------------------------------------------------
	| WordPress plugin functions
	|--------------------------------------------------------------------------
	*/

	if ( ! function_exists( 'get_plugins' ) ) {
		require_once ABSPATH . 'wp-admin/includes/plugin.php';
	}

	$plugins = get_plugins();


	/*
	|--------------------------------------------------------------------------
	| Track what we find and what succeeds
	|--------------------------------------------------------------------------
	*/

	$detected = array();

	$results = array();


	/*
	|--------------------------------------------------------------------------
	| Automatic.css
	|--------------------------------------------------------------------------
	|
	| ACSS 3.x:
	| Store:   https://automaticcss.com/
	| Item ID: 164
	|
	| ACSS 4.x:
	| Store:   https://automaticcss.com/
	| Item ID: 183554
	|
	| Both versions use:
	|
	| automatic_css_license_key
	| automatic_css_license_status
	|--------------------------------------------------------------------------
	*/

	$acss_version = null;


	foreach ( $plugins as $plugin_file => $plugin_data ) {

		$name = isset( $plugin_data['Name'] )
			? strtolower( trim( $plugin_data['Name'] ) )
			: '';

		/*
		 * Detect Automatic.css without relying solely on its directory name.
		 */
		if (
			false !== strpos( $name, 'automatic.css' ) ||
			false !== strpos( $name, 'automatic css' )
		) {

			if ( ! empty( $plugin_data['Version'] ) ) {

				$acss_version = (string) $plugin_data['Version'];

				break;
			}
		}
	}


	if ( null !== $acss_version ) {

		$detected[] = 'automatic-css';

		$acss_major = (int) explode(
			'.',
			$acss_version
		)[0];


		switch ( $acss_major ) {

			/*
			 * Automatic.css 3.x
			 */
			case 3:

				if ( ! defined( 'AUTOMATIC_CSS_3_LICENSE_KEY' ) ) {

					$results['automatic-css'] = false;

					break;
				}


				$results['automatic-css'] = $activate_edd_license(
					'https://automaticcss.com/',
					164,
					'Automatic.css',
					AUTOMATIC_CSS_3_LICENSE_KEY,
					'automatic_css_license_key',
					'automatic_css_license_status'
				);

				break;


			/*
			 * Automatic.css 4.x
			 */
			case 4:

				if ( ! defined( 'AUTOMATIC_CSS_4_LICENSE_KEY' ) ) {

					$results['automatic-css'] = false;

					break;
				}


				$results['automatic-css'] = $activate_edd_license(
					'https://automaticcss.com/',
					183554,
					'Automatic.css',
					AUTOMATIC_CSS_4_LICENSE_KEY,
					'automatic_css_license_key',
					'automatic_css_license_status'
				);

				break;


			/*
			 * Unknown/future ACSS major.
			 *
			 * Don't guess which licence/product ID should be used.
			 */
			default:

				$results['automatic-css'] = false;

				break;
		}
	}


	/*
	|--------------------------------------------------------------------------
	| Frames
	|--------------------------------------------------------------------------
	|
	| Frames 1.5.13 licensing implementation:
	|
	| Store:        https://getframes.io/
	| EDD Item ID:  176
	| Product Name: Frames (Bricks Builder)
	|
	| Options:
	|
	| frames_license_key
	| frames_license_status
	|--------------------------------------------------------------------------
	*/

	$frames_detected = false;


	foreach ( $plugins as $plugin_file => $plugin_data ) {

		$name = isset( $plugin_data['Name'] )
			? strtolower( trim( $plugin_data['Name'] ) )
			: '';

		if (
			'frames' === $name ||
			false !== strpos( $name, 'frames' )
		) {

			/*
			 * Extra pathname check helps avoid treating an unrelated
			 * plugin containing "Frames" in its name as getFrames.
			 */
			if (
				false !== strpos(
					strtolower( $plugin_file ),
					'frames'
				)
			) {

				$frames_detected = true;

				break;
			}
		}
	}


	if ( $frames_detected ) {

		$detected[] = 'frames';


		if ( ! defined( 'FRAMES_LICENSE_KEY' ) ) {

			$results['frames'] = false;

		} else {

			$results['frames'] = $activate_edd_license(
				'https://getframes.io/',
				176,
				'Frames (Bricks Builder)',
				FRAMES_LICENSE_KEY,
				'frames_license_key',
				'frames_license_status'
			);
		}
	}


	/*
	|--------------------------------------------------------------------------
	| Nothing supported installed yet
	|--------------------------------------------------------------------------
	|
	| Leave the snippet enabled.
	|
	| This is useful if Ninja Updater deploys the snippet before the
	| commercial plugins have finished installing.
	|--------------------------------------------------------------------------
	*/

	if ( empty( $detected ) ) {
		return;
	}


	/*
	|--------------------------------------------------------------------------
	| Require ALL detected products to succeed
	|--------------------------------------------------------------------------
	|
	| Examples:
	|
	| ACSS only installed:
	|     ACSS must succeed.
	|
	| Frames only installed:
	|     Frames must succeed.
	|
	| ACSS + Frames installed:
	|     BOTH must succeed.
	|
	| If anything fails, leave this snippet enabled so it can retry.
	|--------------------------------------------------------------------------
	*/

	foreach ( $detected as $product ) {

		if (
			! isset( $results[ $product ] ) ||
			true !== $results[ $product ]
		) {
			return;
		}
	}


	/*
	|--------------------------------------------------------------------------
	| Everything succeeded
	|--------------------------------------------------------------------------
	*/

	$completion_data = array(
		'site_url'     => site_url(),
		'completed_at' => current_time( 'mysql', true ),
		'products'     => array(),
	);


	if ( isset( $results['automatic-css'] ) ) {

		$completion_data['products']['automatic-css'] = array(
			'version' => $acss_version,
			'major'   => isset( $acss_major )
				? $acss_major
				: null,
			'status'  => 'valid',
		);
	}


	if ( isset( $results['frames'] ) ) {

		$completion_data['products']['frames'] = array(
			'status' => 'valid',
		);
	}


	update_option(
		$completed_option,
		$completion_data,
		false
	);


	/*
	|--------------------------------------------------------------------------
	| Remove ourselves from Ninja Updater
	|--------------------------------------------------------------------------
	*/

	$disable_self();

}, 20 );
PHP

Etch and Etch-Theme

This is slightly different; they use SureCart and I have therefore built this one around the SureCart SDK as it stands today

<?php
/**
 * Plugin Name: Ninja Generic SureCart License Activator
 * Description: One-shot activator for SureCart Licensing SDK powered WordPress products.
 * Author: Nathan Foley
 * Version: 2.0.0
 *
 * ============================================================================
 * PURPOSE
 * ============================================================================
 *
 * This utility snippet activates one or more products using the SureCart
 * WordPress Licensing API.
 *
 * Products and license keys are defined in wp-config.php.
 *
 * Once every configured item has either:
 *
 *   1. Already been activated with the configured license, or
 *   2. Been activated successfully by this snippet
 *
 * the snippet removes its own filename from:
 *
 *     ninja_updater_selected_snippets
 *
 * This makes it suitable for temporary deployment using Ninja Updater /
 * Tasks After Install provisioning.
 *
 *
 * ============================================================================
 * WP-CONFIG.PHP EXAMPLE
 * ============================================================================
 *
 * define( 'SURECART_LICENSED_ITEMS', [
 *
 *     [
 *         'name'         => 'Example Plugin',
 *         'item'         => 'exampleplugin',
 *         'license'      => 'YOUR-LICENSE-KEY',
 *         'public_token' => 'pt_xxxxxxxxxxxxxxxxx',
 *     ],
 *
 *     [
 *         'name'         => 'Example Theme',
 *         'item'         => 'exampletheme',
 *         'license'      => 'YOUR-THEME-LICENSE',
 *         'public_token' => 'pt_xxxxxxxxxxxxxxxxx',
 *     ],
 *
 * ] );
 *
 *
 * ============================================================================
 * OPTION NAMING
 * ============================================================================
 *
 * By default:
 *
 *     'item' => 'exampleplugin'
 *
 * results in:
 *
 *     exampleplugin_license_options
 *
 * containing:
 *
 *     [
 *         'sc_license_key'   => '...',
 *         'sc_license_id'    => '...',
 *         'sc_activation_id' => '...',
 *     ]
 *
 *
 * ============================================================================
 * CUSTOM OPTION NAME
 * ============================================================================
 *
 * If a product does not use the normal SDK-derived option name:
 *
 *     [
 *         'name'         => 'Example Plugin',
 *         'item'         => 'example',
 *         'option_name'  => 'custom_license_options',
 *         'license'      => '...',
 *         'public_token' => 'pt_xxx',
 *     ],
 *
 *
 * ============================================================================
 * PRODUCT-SPECIFIC COMPATIBILITY
 * ============================================================================
 *
 * Optional:
 *
 *     'type' => 'etch'
 *
 * Currently supported types:
 *
 *     surecart    Default generic behaviour.
 *     etch        Also updates Etch-specific license state.
 *
 *
 * ============================================================================
 * ETCH EXAMPLE
 * ============================================================================
 *
 * Etch itself supports ETCH_LICENSE_KEY natively, so wp-config.php can contain:
 *
 *     define( 'ETCH_LICENSE_KEY', 'YOUR-ETCH-LICENSE' );
 *
 *     define( 'SURECART_LICENSED_ITEMS', [
 *
 *         [
 *             'name'         => 'Etch',
 *             'item'         => 'etch',
 *             'license'      => ETCH_LICENSE_KEY,
 *             'public_token' => 'pt_xxxxxxxxxxxxxxxxx',
 *             'type'         => 'etch',
 *         ],
 *
 *         [
 *             'name'         => 'Etch Theme',
 *             'item'         => 'etchtheme',
 *             'license'      => 'YOUR-ETCH-THEME-LICENSE',
 *             'public_token' => 'pt_xxxxxxxxxxxxxxxxx',
 *         ],
 *
 *     ] );
 *
 *
 * ============================================================================
 * RETRY BEHAVIOUR
 * ============================================================================
 *
 * If one configured product fails:
 *
 *     Product A  SUCCESS
 *     Product B  SUCCESS
 *     Product C  FAILED
 *
 * this snippet remains enabled.
 *
 * On the next run A and B are detected as already activated, and only C needs
 * another API activation attempt.
 *
 * The snippet disables itself only after ALL configured items succeed.
 *
 *
 * ============================================================================
 * SECURITY
 * ============================================================================
 *
 * License keys and public tokens are read from wp-config.php.
 *
 * This snippet does not duplicate license keys inside its own audit option.
 *
 * Individual plugins may still require their license key in their standard
 * WordPress option because that is part of the SureCart SDK integration.
 *
 *
 * ============================================================================
 * NINJA UPDATER
 * ============================================================================
 *
 * The filename below MUST match the filename stored in:
 *
 *     ninja_updater_selected_snippets
 *
 * Default:
 *
 *     SureCart-License-Activator.php
 *
 * ============================================================================
 */

defined( 'ABSPATH' ) || exit;


add_action(
	'admin_init',
	function () {

		/*
		|--------------------------------------------------------------------------
		| Configuration
		|--------------------------------------------------------------------------
		*/

		$snippet_filename = 'SureCart-License-Activator.php';

		$completed_option =
			'ninja_surecart_license_activator_completed';

		$error_option =
			'ninja_surecart_license_activator_last_errors';


		/*
		|--------------------------------------------------------------------------
		| Validate wp-config configuration
		|--------------------------------------------------------------------------
		*/

		if ( ! defined( 'SURECART_LICENSED_ITEMS' ) ) {
			return;
		}


		$items = SURECART_LICENSED_ITEMS;


		if (
			! is_array( $items ) ||
			empty( $items )
		) {
			return;
		}


		/*
		|--------------------------------------------------------------------------
		| Remove this snippet from Ninja Updater
		|--------------------------------------------------------------------------
		*/

		$disable_self = static function () use ( $snippet_filename ) {

			$selected = get_option(
				'ninja_updater_selected_snippets',
				array()
			);


			if ( ! is_array( $selected ) ) {
				return;
			}


			$updated = array_values(
				array_filter(
					$selected,
					static function ( $filename ) use ( $snippet_filename ) {

						return (string) $filename !==
							$snippet_filename;
					}
				)
			);


			if ( $updated !== $selected ) {

				update_option(
					'ninja_updater_selected_snippets',
					$updated,
					false
				);
			}
		};


		/*
		|--------------------------------------------------------------------------
		| SureCart API request
		|--------------------------------------------------------------------------
		|
		| Mirrors the SureCart WordPress Licensing SDK request structure.
		|--------------------------------------------------------------------------
		*/

		$surecart_request = static function (
			$method,
			$route,
			$public_token,
			$body = null
		) {

			$headers = array(
				'X-SURECART-WP-LICENSING-SDK-VERSION' => '1.0.2',
				'Accept'                              => 'application/json',
				'Authorization'                       =>
					'Bearer ' . $public_token,
			);


			$args = array(
				'headers' => $headers,
				'method'  => strtoupper( $method ),
				'timeout' => 30,
			);


			if ( null !== $body ) {
				$args['body'] = $body;
			}


			$response = wp_remote_request(
				'https://api.surecart.com/' .
				ltrim( $route, '/' ),
				$args
			);


			if ( is_wp_error( $response ) ) {
				return $response;
			}


			$status = wp_remote_retrieve_response_code(
				$response
			);


			$raw_body = wp_remote_retrieve_body(
				$response
			);


			$decoded = json_decode( $raw_body );


			/*
			 * SureCart commonly responds with:
			 *
			 * 200 OK
			 * 201 Created
			 */
			if (
				200 !== $status &&
				201 !== $status
			) {

				$message = sprintf(
					'SureCart API returned HTTP %d.',
					$status
				);


				if (
					is_object( $decoded ) &&
					! empty( $decoded->message )
				) {
					$message .= ' ' .
						sanitize_text_field(
							(string) $decoded->message
						);
				}


				return new WP_Error(
					'surecart_api_error',
					$message,
					array(
						'status' => $status,
						'body'   => $decoded,
					)
				);
			}


			if ( null === $decoded ) {

				return new WP_Error(
					'surecart_invalid_json',
					'SureCart returned an invalid JSON response.'
				);
			}


			return $decoded;
		};


		/*
		|--------------------------------------------------------------------------
		| Determine the WordPress option name for an item
		|--------------------------------------------------------------------------
		*/

		$get_option_name = static function ( array $item ) {

			if ( ! empty( $item['option_name'] ) ) {

				return sanitize_key(
					(string) $item['option_name']
				);
			}


			if ( empty( $item['item'] ) ) {
				return '';
			}


			$item_name = sanitize_key(
				(string) $item['item']
			);


			/*
			 * Allow a fully-qualified option name to be supplied
			 * without adding the suffix twice.
			 */
			if (
				str_ends_with(
					$item_name,
					'_license_options'
				)
			) {
				return $item_name;
			}


			return $item_name .
				'_license_options';
		};


		/*
		|--------------------------------------------------------------------------
		| Product-specific compatibility
		|--------------------------------------------------------------------------
		*/

		$apply_product_compatibility =
			static function (
				$type,
				$license_key
			) {

				switch ( $type ) {

					/*
					 * Etch plugin compatibility.
					 *
					 * Etch additionally checks these options.
					 */
					case 'etch':

						update_option(
							'etch_license_key',
							$license_key,
							false
						);

						update_option(
							'etch_license_status',
							'valid',
							false
						);

						delete_transient(
							'etch_license_is_active'
						);

						break;


					/*
					 * Generic SureCart SDK product.
					 */
					case 'surecart':
					default:
						break;
				}
			};


		/*
		|--------------------------------------------------------------------------
		| Check whether one item is already activated
		|--------------------------------------------------------------------------
		*/

		$is_already_activated =
			static function (
				$option_name,
				$license_key
			) {

				$stored = get_option(
					$option_name,
					array()
				);


				if ( ! is_array( $stored ) ) {
					return false;
				}


				if (
					empty( $stored['sc_license_key'] ) ||
					empty( $stored['sc_license_id'] ) ||
					empty( $stored['sc_activation_id'] )
				) {
					return false;
				}


				return hash_equals(
					(string) $license_key,
					(string) $stored['sc_license_key']
				);
			};


		/*
		|--------------------------------------------------------------------------
		| Activate one configured product
		|--------------------------------------------------------------------------
		*/

		$activate_item =
			static function ( array $item ) use (
				$surecart_request,
				$get_option_name,
				$is_already_activated,
				$apply_product_compatibility
			) {

				/*
			 * Display name.
			 */
				$display_name =
					! empty( $item['name'] )
					? sanitize_text_field(
						(string) $item['name']
					)
					: 'Unnamed SureCart Product';


				/*
			 * Validate configuration.
			 */
				if ( empty( $item['item'] ) ) {

					return new WP_Error(
						'surecart_missing_item',
						sprintf(
							'%s is missing the item value.',
							$display_name
						)
					);
				}


				if ( empty( $item['license'] ) ) {

					return new WP_Error(
						'surecart_missing_license',
						sprintf(
							'%s is missing its license key.',
							$display_name
						)
					);
				}


				if ( empty( $item['public_token'] ) ) {

					return new WP_Error(
						'surecart_missing_token',
						sprintf(
							'%s is missing its SureCart public token.',
							$display_name
						)
					);
				}


				$item_name = sanitize_key(
					(string) $item['item']
				);


				$license_key = trim(
					(string) $item['license']
				);


				$public_token = trim(
					(string) $item['public_token']
				);


				$type =
					! empty( $item['type'] )
					? sanitize_key(
						(string) $item['type']
					)
					: 'surecart';


				$option_name =
					$get_option_name( $item );


				if ( '' === $option_name ) {

					return new WP_Error(
						'surecart_invalid_option',
						sprintf(
							'Could not determine the license option for %s.',
							$display_name
						)
					);
				}


				/*
				|--------------------------------------------------------------------------
				| Already activated
				|--------------------------------------------------------------------------
				*/

				if (
					$is_already_activated(
						$option_name,
						$license_key
					)
				) {

					/*
					 * Ensure any compatibility options also exist.
					 */
					$apply_product_compatibility(
						$type,
						$license_key
					);


					$stored = get_option(
						$option_name,
						array()
					);


					return array(
						'name'          => $display_name,
						'item'          => $item_name,
						'option_name'   => $option_name,
						'type'          => $type,
						'license_id'    =>
							(string) $stored['sc_license_id'],
						'activation_id' =>
							(string) $stored['sc_activation_id'],
						'already_valid' => true,
					);
				}


				/*
				|--------------------------------------------------------------------------
				| Step 1: Validate / retrieve license
				|--------------------------------------------------------------------------
				*/

				$license = $surecart_request(
					'GET',
					'v1/public/licenses/' .
					rawurlencode( $license_key ),
					$public_token
				);


				if ( is_wp_error( $license ) ) {
					return $license;
				}


				if (
					! is_object( $license ) ||
					empty( $license->id )
				) {

					return new WP_Error(
						'surecart_invalid_license_response',
						sprintf(
							'SureCart did not return a license ID for %s.',
							$display_name
						)
					);
				}


				$license_id =
					(string) $license->id;


				/*
				|--------------------------------------------------------------------------
				| Step 2: Create activation
				|--------------------------------------------------------------------------
				*/

				$activation =
					$surecart_request(
						'POST',
						'v1/public/activations',
						$public_token,
						array(
							'activation' => array(
								'fingerprint' =>
									esc_url_raw(
										get_site_url()
									),

								'name' =>
									get_bloginfo(
										'name'
									),

								'license' =>
									$license_id,
							),
						)
					);


				if ( is_wp_error( $activation ) ) {
					return $activation;
				}


				if (
					! is_object( $activation ) ||
					empty( $activation->id )
				) {

					return new WP_Error(
						'surecart_invalid_activation_response',
						sprintf(
							'SureCart did not return an activation ID for %s.',
							$display_name
						)
					);
				}


				$activation_id =
					(string) $activation->id;


				/*
				|--------------------------------------------------------------------------
				| Step 3: Store SureCart SDK license state
				|--------------------------------------------------------------------------
				*/

				$license_options = array(

					/*
					 * Retained for compatibility with products using
					 * the same structure as your existing activator.
					 */
					0 => false,

					'sc_license_key' =>
						$license_key,

					'sc_license_id' =>
						$license_id,

					'sc_activation_id' =>
						$activation_id,
				);


				update_option(
					$option_name,
					$license_options,
					false
				);


				/*
				|--------------------------------------------------------------------------
				| Step 4: Verify storage
				|--------------------------------------------------------------------------
				*/

				$stored = get_option(
					$option_name,
					array()
				);


				if (
					! is_array( $stored ) ||
					empty(
						$stored['sc_activation_id']
					) ||
					! hash_equals(
						$activation_id,
						(string)
							$stored['sc_activation_id']
					)
				) {

					return new WP_Error(
						'surecart_storage_failed',
						sprintf(
							'Activation succeeded but WordPress could not store the license data for %s.',
							$display_name
						)
					);
				}


				/*
				|--------------------------------------------------------------------------
				| Step 5: Product compatibility
				|--------------------------------------------------------------------------
				*/

				$apply_product_compatibility(
					$type,
					$license_key
				);


				return array(
					'name'          => $display_name,
					'item'          => $item_name,
					'option_name'   => $option_name,
					'type'          => $type,
					'license_id'    => $license_id,
					'activation_id' => $activation_id,
					'already_valid' => false,
				);
			};


		/*
		|--------------------------------------------------------------------------
		| Process every configured product
		|--------------------------------------------------------------------------
		*/

		$completed = array();
		$failed    = array();


		foreach ( $items as $index => $item ) {

			if ( ! is_array( $item ) ) {

				$failed[] = array(
					'index' => $index,
					'error' =>
						'Configuration entry is not an array.',
				);

				continue;
			}


			$result =
				$activate_item( $item );


			if ( is_wp_error( $result ) ) {

				$name =
					! empty( $item['name'] )
					? sanitize_text_field(
						(string) $item['name']
					)
					: sprintf(
						'Item %s',
						(string) $index
					);


				$failed[] = array(
					'name'  => $name,
					'item'  =>
						! empty( $item['item'] )
						? sanitize_key(
							(string) $item['item']
						)
						: '',
					'error' =>
						$result->get_error_message(),
				);


				error_log(
					sprintf(
						'SureCart activation failed for %s: %s',
						$name,
						$result->get_error_message()
					)
				);


				continue;
			}


			$completed[] = $result;
		}


		/*
		|--------------------------------------------------------------------------
		| One or more failures
		|--------------------------------------------------------------------------
		|
		| Keep this snippet enabled.
		|--------------------------------------------------------------------------
		*/

		if ( ! empty( $failed ) ) {

			update_option(
				$error_option,
				array(
					'site_url' =>
						get_site_url(),

					'time' =>
						current_time(
							'mysql',
							true
						),

					'errors' =>
						$failed,
				),
				false
			);


			return;
		}


		/*
		|--------------------------------------------------------------------------
		| Everything succeeded
		|--------------------------------------------------------------------------
		*/

		delete_option(
			$error_option
		);


		$audit_items = array();


		foreach ( $completed as $result ) {

			$audit_items[] = array(
				'name'          =>
					$result['name'],

				'item'          =>
					$result['item'],

				'type'          =>
					$result['type'],

				'option_name'   =>
					$result['option_name'],

				'license_id'    =>
					$result['license_id'],

				'activation_id' =>
					$result['activation_id'],
			);
		}


		update_option(
			$completed_option,
			array(
				'site_url' =>
					get_site_url(),

				'completed_at' =>
					current_time(
						'mysql',
						true
					),

				'items' =>
					$audit_items,
			),
			false
		);


		/*
		|--------------------------------------------------------------------------
		| Self-disable
		|--------------------------------------------------------------------------
		*/

		$disable_self();
	},
	20
);
PHP

Both snippets are designed to run, and once successful, they deactivate themselves from my utility plugin. You could do the same or something similar for your installation too; you could also add it to your version of tasks after installation.

Support the Author

Support my work
Really Useful Plugin Logo
Wpvideobank temp
Appoligies for any spelling and grammer issue. As a dyslexic i need to rely on tools which includes AI for this they like me are not perfect but I do try my best