Skip to content

Hooks & filters

Ultimate Watermark exposes actions and filters across both plugins so you can add behaviour without forking. This page lists the most useful ones with file:line references.

Some marketing-mentioned hooks are subscribed but never fired in the current build. Those are flagged below as dead.

Bootstrap & lifecycle

HookTypeArgsWhenFile:line
ultimate_watermark_initaction$pluginAfter textdomain & migration.Plugin.php:240
ultimate_watermark_admin_initaction$pluginAdmin bootstrap.Plugin.php:254
ultimate_watermark_enqueue_assetsaction$pluginInside enqueue cycle.Plugin.php:268
ultimate_watermark_deactivateaction$pluginPlugin deactivation.Plugin.php:285
php
add_action( 'ultimate_watermark_init', function ( $plugin ) {
    // Register custom watermark types or dynamic placeholders.
} );

Settings

HookTypeUse
ultimate_watermark_settings_configfilterModify settings field config rendered on the Settings page.
ultimate_watermark_settings_tabsfilterAdd tabs to the Settings page.
ultimate_watermark_load_frontend_assetsfilterDecide whether to enqueue right-click protection JS.
php
add_filter( 'ultimate_watermark_settings_config', function ( $config ) {
    $config['general']['my_extra_field'] = [
        'label'   => 'My extra field',
        'type'    => 'checkbox',
        'default' => '0',
    ];
    return $config;
} );

ultimate_watermark_settings_fields (subscribed in ProAdminManager.php:29) is dead — Free SettingsPage doesn't apply it. Use ultimate_watermark_settings_config instead.

Watermark builder form

HookTypeUseFile:line
ultimate_watermark_type_optionsfilterAdd new watermark types (beyond text/image).AddWatermarkPage.php:645
ultimate_watermark_text_settings_fieldsfilterAdd fields to the text-watermark Appearance tab.:665
ultimate_watermark_add_form_sectionsfilterAdd a new section to the Add Watermark form.:994
ultimate_watermark_rules_sectionsfilterAdd to the Rules tab.:1000
ultimate_watermark_form_tabsfilterAdd a new tab to the builder.:1006
ultimate_watermark_after_textarea_fieldactionRender extra HTML after a textarea field (Pro uses for placeholder helper).:418
php
// Add a "Stamp profile" watermark type alongside text/image.
add_filter( 'ultimate_watermark_type_options', function ( $types ) {
    $types['stamp_profile'] = 'Stamp profile';
    return $types;
} );

Rules evaluator

HookTypeArgsUseFile:line
uwm_condition_typesfilter$typesRegister a custom rule type.AddWatermarkPage.php:1082
uwm_evaluate_conditionfilter$matches, $rule, $contextEvaluate a rule for a given image context.RulesEvaluator.php:135
uwm_condition_context_valuefilter$value, $rule, $contextOverride the value pulled from context for a rule.:246
uwm_compare_valuesfilter$matches, $left, $operator, $rightOverride comparison logic for a rule.:278

See Conditional rules → Custom rule types via filter for a full example.

Watermark data resolver

HookTypeUseFile:line
ultimate_watermark_sanitize_typefilterSanitize the type value during save.WatermarkDataResolver.php:95
ultimate_watermark_before_normalize_datafilterModify raw data before normalisation.:131
ultimate_watermark_after_normalize_datafilterModify normalised data before persistence.:198
ultimate_watermark_sanitized_datafilterFinal sanitization pass.WatermarkAjaxHandler.php:210

Save lifecycle

HookTypeArgsWhen
ultimate_watermark_savedaction$watermark_id, $dataAfter save (WatermarkAjaxHandler.php:574).
ultimate_watermark_security_violationaction$type, $contextSecurity guard tripped.
php
add_action( 'ultimate_watermark_saved', function ( $id, $data ) {
    // Sync watermark to a CDN edge config.
}, 10, 2 );

Processors

HookTypeArgsUseFile:line
ultimate_watermark_apply_custom_typeaction$image, $watermarkData, $typeApply a custom raster type that GD/Imagick processors don't know.GDWatermarkProcessor.php:294
ultimate_watermark_handle_custom_typefilter$result, $image, $data, $typeReturn a non-false value to short-circuit and supply your own rendered image.:279
php
add_filter( 'ultimate_watermark_handle_custom_type', function ( $result, $image, $data, $type ) {
    if ( $type !== 'qr' ) return $result;
    // ... render QR onto $image, return modified GD/Imagick handle ...
    return $image;
}, 10, 4 );

Frontend / data

HookTypeUseFile:line
ultimate_watermark_load_frontend_assetsfilter (bool)Whether to load right-click / drag-protection JS.AssetManager.php:130
ultimate_watermark_build_datafilterTweak the data passed to the frontend (e.g. extra image URLs).WatermarkHelper.php:168
ultimate_watermark_statisticsfilterModify stats for the Analytics page.WatermarkHelper.php:873

Pro: dynamic content

HookTypeArgsUse
ultimate_watermark_pro_register_dynamic_typesaction$managerRegister additional placeholder types.
ultimate_watermark_pro_resolve_placeholderfilter($value, $placeholder, $data)Replace what a placeholder renders.
php
add_filter( 'ultimate_watermark_pro_resolve_placeholder', function ( $value, $placeholder, $data ) {
    if ( $placeholder === 'order_id' && ! empty( $data['post_id'] ) ) {
        return get_post_meta( $data['post_id'], '_order_id', true );
    }
    return $value;
}, 10, 3 );

License updater (Pro)

HookTypeUse
in_plugin_update_message-{$file}actionCustom update message row (WP core).
edd_sl_api_request_verify_sslfilterSSL verify for EDD updater.
https_local_ssl_verifyfilterLicense HTTP SSL switch.

Hooks that look like hooks but aren't

The following are subscribed in code but never fired — flagged for documentation honesty:

HookReason
ultimate_watermark_before_applyPro DynamicWatermarkProcessor.php:22 subscribes; no do_action exists in either plugin. Treat as no-op.
ultimate_watermark_admin_enqueue_scriptsPro ProPlugin.php:117 subscribes; never fired. The real admin enqueue is ProAdminManager::enqueueAssets.
ultimate_watermark_settings_fieldsPro ProAdminManager.php:29 subscribes; the free SettingsPage doesn't apply it. Use ultimate_watermark_settings_config instead.

Tip: discover all hooks at runtime

Drop this in wp-content/mu-plugins/uw-hook-trace.php:

php
<?php
add_action( 'all', function ( $hook_name ) {
    if ( strpos( $hook_name, 'ultimate_watermark' ) === 0
      || strpos( $hook_name, 'uwm_' ) === 0 ) {
        error_log( "[Ultimate Watermark hook] $hook_name" );
    }
} );

This logs every plugin hook that fires during a request.

Where to go next