SaveTo Wishlist for WooCommerce
Get Started
How to extend SaveTo Wishlist Pro with hooks and the REST API - SaveTo Wishlist
  1. Home
  2. Knowledge Base
  3. Wishlist
  4. Developer Guides
  5. How to extend SaveTo Wishlist Pro with hooks and the REST API
  1. Home
  2. Knowledge Base
  3. Wishlist
  4. How to extend SaveTo Wishlist Pro with hooks and the REST API

How to extend SaveTo Wishlist Pro with hooks and the REST API

Need to change how SaveTo Wishlist Pro behaves without editing the plugin? You can do it with WordPress hooks and the plugin’s REST API. This article lists the hooks and routes you can use, with the arguments each one passes and short PHP examples. Everything here applies to SaveTo Wishlist Pro 1.0.4.

Before you start

SaveTo Wishlist Pro runs on top of SaveTo Wishlist Lite, so both plugins must be active. Put your hook code in a small custom plugin or a must-use plugin, not in the SaveTo Wishlist Pro files, because plugin updates replace those files.

Every Pro hook name starts with stwpro_. The hooks for the free plugin are covered in How to extend SaveTo Wishlist with hooks and the REST API.

The hooks and filters below are listed with the arguments they pass. When you add a filter, set the accepted argument count to match, or WordPress only passes you the first argument. Return the first argument (or a changed copy of it) from every filter.

REST API routes

All SaveTo Wishlist Pro routes use the namespace saveto-wishlist-pro/v1, so the full URL looks like https://example.com/wp-json/saveto-wishlist-pro/v1/analytics/products-insight.

Who can call the routes

The analytics, automations, default wishlists and license routes serve the plugin’s own admin screens, and they may change. They only answer requests from a logged-in user who has the manage_options capability (administrators by default). Anyone else gets a 401 or 403 error. Send the request with a normal WordPress login session and a REST nonce, or with any other REST authentication method your site supports.

The analytics read routes, the automations routes and the license routes also have a rate limit per user. Read requests (GET) get 300 requests per minute. All other methods get 60 requests per minute. When you go over, the route returns a 429 error with the code rate_limit_exceeded. You can change the limits with the stwpro_api_rate_limit filter, covered below.

Analytics routes

The base path is /analytics.

RouteMethodWho can call itWhat it does
/analytics/products-insightGETAdministrators, rate limitedReturns most popular, trending and recently added products. Accepts period with the value 7days or 30days. The default is 7days.
/analytics/category-brand-insightGETAdministrators, rate limitedReturns category and brand insights.
/analytics/engagement-insightGETAdministrators, rate limitedReturns engagement insights for products.
/analytics/timebased-trendsGETAdministrators, rate limitedReturns trends over time. Accepts range with the value 7days, 30days, 90days or 365days. The default is 30days.
/analytics/customer-behaviorGETAdministrators, rate limitedReturns customer behavior insights, including top wishlisters and customer segments.
/analytics/refreshPOSTAdministratorsClears the analytics caches. A user can refresh once every 30 seconds. A faster request returns a 429 error with the code cooldown_active.

The analytics responses are cached for one hour by default. A successful call to /analytics/refresh clears the cache, so the next read returns fresh data.

This example reads the trending products for the last 30 days from the browser, in a script that runs on a WordPress admin screen:

wp.apiFetch( {
    path: '/saveto-wishlist-pro/v1/analytics/products-insight?period=30days',
} ).then( ( data ) => {
    console.log( data.most_popular, data.trending, data.recently_added );
} );

Automation routes

The base path is /automations. All four routes need an administrator and are rate limited.

RouteMethodWhat it does
/automations/get-automationsGETReturns saved automations. Query parameters are used as filters.
/automations/save-automationPOSTCreates or updates an automation. It reads id, trigger_type, action_type, status, description and action_data.
/automations/delete-automationDELETEDeletes the automation with the ID in the id parameter. Returns a 400 error when the ID is empty.
/automations/send-test-emailPOSTSends a test email with dummy data. It reads email_to, email_subject and email_body.

Default wishlists routes

The base path is /default-wishlists. All routes need an administrator.

RouteMethodWhat it does
/default-wishlists/settingsGET, POSTReads or saves the default wishlist settings. The POST request reads the list parameter.
/default-wishlists/migration-statusGETReturns the progress of the job that creates default wishlists for existing users who have none, and how many users are still eligible.
/default-wishlists/start-migrationPOSTStarts that job.
/default-wishlists/cancel-migrationPOSTCancels that job.

Webhook route

The route /webhook/wishlist-created is different from the others. It does not use a WordPress login. It uses the webhook API key, sent in the x-api-key header or the api_key query parameter, and it answers 401 when the key is missing or wrong. A POST request fires the stwpro_wishlist_created action. A GET request with a wishlist_id parameter returns a public, published wishlist. For setup and security details, read How to connect external tools using wishlist webhooks and How to secure the SaveTo Wishlist Pro webhook API endpoint.

Filters for the route permissions

FilterArgumentsWhat it does
stwpro_api_admin_permissions_check$response, $requestFilters the result of the administrator check on the admin-only routes. Return true to allow, or a WP_Error to deny.
stwpro_webhook_permissions_check$response, $requestFilters the result of the API key check on the webhook route.
stwpro_api_rate_limit$limit, $request, $is_readSets the requests allowed per minute. The defaults are 300 for read requests and 60 for the rest.
stwpro_api_rate_limit_check$result, $requestFilters the final result of the rate limit check.

For example, this raises the write limit to 120 requests per minute:

add_filter( 'stwpro_api_rate_limit', function ( $limit, $request, $is_read ) {
    return $is_read ? $limit : 120;
}, 10, 3 );

Automation hooks

Automations connect a trigger, such as a product going on sale, to an action, such as sending an email. These hooks let you add your own actions and change what the built-in actions send.

Add your own automation action

Two filters work together. Use stwpro_automation_actions to add your action to the list of actions, and use stwpro_automation_action_handlers to say which function runs it. The built-in action types are send_email, call_webhook and update_user_meta.

FilterArgumentsWhat it does
stwpro_automation_actions$actionsFilters the list of action types. Each item is an action key and its label.
stwpro_automation_action_handlers$handlersFilters the map of action type to handler. The handler must be callable. If your callback returns something other than an array, the plugin ignores it and keeps the built-in handlers.

WordPress calls your handler with five arguments: the active automations of that type for the trigger, the automation data, the trigger context object, a boolean for the product category condition, and an array of extra parameters.

add_filter( 'stwpro_automation_actions', function ( $actions ) {
    $actions['send_to_crm'] = __( 'Send to my CRM', 'my-plugin' );
    return $actions;
} );

add_filter( 'stwpro_automation_action_handlers', function ( $handlers ) {
    $handlers['send_to_crm'] = 'my_plugin_process_crm_automations';
    return $handlers;
} );

function my_plugin_process_crm_automations( $automations, $automation_data, $context_data, $category_condition, $params ) {
    foreach ( $automations as $automation ) {
        // Send $automation_data to your CRM here.
    }
}

Change who receives an automation email

Two filters set the email recipient. stwpro_automation_filter_email_to_customer runs once per wishlist owner for the product on sale and product back in stock triggers. stwpro_automation_filter_email_to runs for every other trigger. With both filters, an empty or invalid address skips the email.

FilterArguments
stwpro_automation_filter_email_to$email_to, $action_data, $context_data, $data, $params
stwpro_automation_filter_email_to_customer$email_to, $action_data, $per_customer_data, $context_data, $params

This example sends every automation email to a test address on a staging site, and skips customers who opted out:

add_filter( 'stwpro_automation_filter_email_to', function ( $email_to ) {
    if ( 'production' !== wp_get_environment_type() ) {
        return 'dev@example.com';
    }
    return $email_to;
}, 10, 1 );

add_filter( 'stwpro_automation_filter_email_to_customer', function ( $email_to, $action_data, $per_customer_data ) {
    $customer_id = (int) ( $per_customer_data['customer_id'] ?? 0 );
    if ( $customer_id && get_user_meta( $customer_id, 'no_wishlist_alerts', true ) ) {
        return '';
    }
    return $email_to;
}, 10, 3 );

Change automation content and data

These four filters pass the value you filter first. The next arguments are the automation record, the action settings, the trigger context, the resolved variable data and the extra parameters. They run before the plugin replaces the variable tags, so your changes can still contain tags such as {customer_name}.

FilterArgumentsWhat it filters
stwpro_automation_email_subject_template$subject_template, $automation, $action_data, $context_data, $data, $paramsThe raw email subject.
stwpro_automation_email_message_template$message_template, $automation, $action_data, $context_data, $data, $paramsThe raw email message.
stwpro_automation_webhook_payload_template$payload_template, $automation, $action_data, $context_data, $data, $paramsThe raw webhook payload.
stwpro_automation_usermeta_meta_value_template$meta_value, $automation, $action_data, $context_data, $data, $paramsThe raw value for the update user meta action.

Three more filters have their own arguments:

FilterArgumentsWhat it filters
stwpro_automation_variables$trigger_variables, $trigger_typeThe variable tags available for a trigger.
stwpro_automation_webhook_recipes$recipesThe webhook quick-start recipes.
stwpro_automations_get_all_automations$automations, $trigger_type, $action_typeThe active automations for a trigger and action type.

For the variable data of each trigger, use one of these filters. They all pass $variable_data, $trigger_type, $context_data.

  • stwpro_automation_data_wishlist_created
  • stwpro_automation_data_item_added_to_wishlist
  • stwpro_automation_data_item_removed_from_wishlist
  • stwpro_automation_data_product_on_sale
  • stwpro_automation_data_product_back_in_stock

Analytics hooks

Customer tier and segment thresholds

The customer analytics put each top wishlister into a tier. A customer reaches a tier when both numbers are met: the wishlist count and the total amount spent. The plugin checks the tiers from platinum down to bronze, and customers who meet none are regular. Each filter takes one argument, the default value, and returns a number.

TierWishlist count filterDefaultSpent filterDefault
Platinumstwpro_admin_platinum_threshold8stwpro_admin_platinum_spent_threshold1500
Goldstwpro_admin_gold_threshold5stwpro_admin_gold_spent_threshold800
Silverstwpro_admin_silver_threshold3stwpro_admin_silver_spent_threshold400
Bronzestwpro_admin_bronze_threshold2stwpro_admin_bronze_spent_threshold200
add_filter( 'stwpro_admin_platinum_threshold', function () {
    return 10;
} );

add_filter( 'stwpro_admin_platinum_spent_threshold', function () {
    return 2500;
} );

Other analytics filters change the customer segments and the lists shown on the analytics screens:

FilterArgumentsDefaultWhat it does
stwpro_admin_vip_threshold$value5Wishlist count for the VIP customers segment.
stwpro_admin_vip_spent_threshold$value800Total spent for the VIP customers segment.
stwpro_admin_inactive_days$value90Days without activity before a customer counts as inactive.
stwpro_admin_top_wishlisters_limit$limit15How many customers the top wishlisters list returns.
stwpro_admin_top_wishlisters_excluded_roles$excluded_rolesarray( 'administrator', 'shop_manager' )Roles left out of the top wishlisters list.
stwpro_admin_customer_segments$segments, $total_customersNoneThe final list of customer segments.

Analytics data, cache and refresh

HookType and argumentsWhat it does
stwpro_analytics_products_insight_dataFilter: $products_insight, $requestChanges the data the products-insight route returns.
stwpro_analytics_products_insight_cache_durationFilter: $secondsSets how long that response is cached. The default is one hour. The category and brand, engagement, time-based trends and customer behavior routes have matching filters: stwpro_analytics_category_brand_insight_cache_duration, stwpro_analytics_engagement_insight_cache_duration, stwpro_analytics_timebased_trends_cache_duration and stwpro_analytics_customer_behavior_cache_duration.
stwpro_analytics_refresh_cooldownFilter: $secondsSets the seconds a user waits between refreshes. The default is 30. Return 0 to turn the wait off.
stwpro_analytics_refreshedAction: $timestampRuns after a refresh clears the caches. Use it to rebuild your own derived data.

The thresholds above are read when the analytics are calculated. If you change one and the screen does not change, refresh the analytics so the cached results are rebuilt.

Default wishlists hooks

These hooks control the wishlists that Pro creates automatically for new users.

HookType and argumentsWhat it does
stwpro_default_wishlists_sync_thresholdFilter: $thresholdIf the configured list has more wishlists than this number, Pro creates them in the background with Action Scheduler instead of during registration. The default is 3.
stwpro_default_wishlists_max_entriesFilter: $maxThe most default wishlists you can save in the list. The default is 20.
stwpro_after_seed_default_wishlistsAction: $user_id, $created, $listRuns after a user receives the default wishlists. $created is the number of wishlists created. It does not run when none were created.
add_action( 'stwpro_after_seed_default_wishlists', function ( $user_id, $created, $list ) {
    update_user_meta( $user_id, 'default_wishlists_created', $created );
}, 10, 3 );

Other hooks

HookType and argumentsWhat it does
stwpro_wholesale_priceFilter: $price, $product_id, $user, $user_wholesale_roleLets another wholesale plugin supply the wholesale price. Return a float to skip the Wholesale Prices lookup. Return false to use the default lookup.
stwpro_disable_abilitiesFilter: $disabledReturn true to stop Pro from registering its abilities. You can also define the constant STWPRO_DISABLE_ABILITIES as true.
stwpro_show_powered_by_in_emailFilter: $showReturn false to remove the “Powered by SaveTo Wishlist” line from emails sent by Pro.
stwpro_wishlist_createdAction: $wishlist_data, $wishlist_itemsRuns when a valid POST request reaches the webhook route /webhook/wishlist-created.
add_filter( 'stwpro_show_powered_by_in_email', '__return_false' );

Frequently asked questions

Can I call the analytics or automations routes from outside WordPress?
Only as a logged-in administrator. These routes check for the manage_options capability and serve the plugin’s own screens, so build on the hooks above for anything that must stay stable. For outside systems, use the webhook route with its API key.

Why do my threshold changes not show on the analytics screen?
The analytics results are cached, for one hour by default. Refresh the analytics, or shorten the cache with the cache duration filters, and the new thresholds apply.

Need help?

If you have a question or run into any issues, we’re here to help.

Was this article helpful?

Related Articles

Need Support?

Can't find the answer you're looking for?
Contact Support
Complete Your Purchase