Extending License Server

SLSWC provides many extension points for developers to customize behavior without modifying core files.


Custom Settings Tabs

Add new settings sections via the slswc_get_sections_{id} filter and populate them with fields via slswc_get_settings_{id}:

add_filter( 'slswc_get_sections_slswc', function ( $sections ) {
    $sections['my_custom_tab'] = 'My Custom Tab';
    return $sections;
} );

add_filter( 'slswc_get_settings_slswc', function ( $settings ) {
    $settings['my_custom_tab'] = array(
        array(
            'id'      => 'my_custom_option',
            'title'   => 'My Custom Option',
            'type'    => 'text',
            'default' => '',
            'desc'    => 'Description of the option.',
        ),
    );
    return $settings;
} );

Settings are saved and loaded automatically through the REST API.

Custom Tools

A custom tool needs two filters: slswc_server_tools maps the tool ID to the callable that runs it, and slswc_tools_settings adds the button to the Settings > Tools tab:

add_filter( 'slswc_server_tools', function ( $tools ) {
    $tools['my_custom_tool'] = 'my_tool_callback';
    return $tools;
} );

add_filter( 'slswc_tools_settings', function ( $settings ) {
    $button = array(
        'title' => 'My Custom Tool',
        'desc'  => 'Does something useful.',
        'id'    => 'my_custom_tool',
        'type'  => 'tool-button',
    );
    // Insert before the closing sectionend field.
    array_splice( $settings, count( $settings ) - 1, 0, array( $button ) );
    return $settings;
} );

See Settings > Tools for a complete example.

The tool's execution is triggered via POST /settings/tools/{tool_id} and the slswc_tools_process_{tool_id} action is fired:

add_action( 'slswc_tools_process_my_custom_tool', function ( $tools ) {
    // Execute the tool logic
} );

Custom Payment Gateways

Register additional payment gateways with the slswc_payment_gateways filter:

add_filter( 'slswc_payment_gateways', function ( $gateways ) {
    $gateways[] = 'My_Custom_Payment_Gateway';
    return $gateways;
} );

See Payment Gateway Development for the full implementation guide.

Template Overrides

SLSWC templates can be overridden from your theme. Copy the template file from the plugin's templates/ directory to your theme under slswc/:

Plugin:  wp-content/plugins/slswc/templates/dashboard/product/license-panel.php
Theme:   wp-content/themes/your-theme/slswc/dashboard/product/license-panel.php

Custom My Account Endpoints

Add new WooCommerce My Account pages using the slswc_add_endpoints action and slswc_my_account_query_vars / slswc_my_account_menu_links filters:

add_action( 'slswc_add_endpoints', function () {
    add_rewrite_endpoint( 'my-custom-page', EP_ROOT | EP_PAGES );
} );

add_filter( 'slswc_my_account_query_vars', function ( $vars ) {
    $vars['my-custom-page'] = 'my-custom-page';
    return $vars;
} );

add_filter( 'slswc_my_account_menu_links', function ( $items, $all_items ) {
    $items['my-custom-page'] = 'My Custom Page';
    return $items;
}, 10, 2 );

Remember to flush rewrite rules after adding new endpoints.

API Namespace Customization

Change the REST API namespace from slswc/v1 to your own:

add_filter( 'slswc_api_namespace', function () {
    return 'my-product/v1';
} );

Warning: Changing the namespace will break compatibility with the standard SLSWC Client library unless you also update the client configuration.

Custom Renewal Periods

Add custom renewal period options:

add_filter( 'slswc_renewal_periods', function ( $periods ) {
    $periods['semi_annual'] = array(
        'label'    => 'Semi-Annual',
        'duration' => '+6 months',
    );
    return $periods;
} );

Or manage them via the REST API: POST /settings/renewal-periods.

Custom License Panel Fields

Add custom field types to the WooCommerce product license panel:

add_action( 'slswc_license_panel_field_my_field_type', function ( $key, $details ) {
    // Render your custom field HTML
    echo '<input type="text" name="' . esc_attr( $key ) . '" />';
}, 10, 2 );

Custom Software Product Properties

Filter the properties set on software products:

add_filter( 'slswc_set_software_props', function ( $props ) {
    $props['my_custom_prop'] = 'value';
    return $props;
} );

Composer Repository Customization

Modify the Composer packages.json output:

// Add extra metadata to all packages
add_filter( 'slswc_composer_package_entry', function ( $entry, $product ) {
    $entry['extra']['installer-name'] = $product->get_slug();
    return $entry;
}, 10, 2 );

// Include expired licenses in Composer access
add_filter( 'slswc_composer_valid_license_statuses', function ( $statuses ) {
    $statuses[] = 'expired';
    return $statuses;
} );

DRM Customization

Override DRM behavior for the client library:

// Extend grace period
add_filter( 'slswc_drm_config_my-plugin', function ( $config ) {
    $config['grace_soft_days'] = 5;
    $config['grace_lock_days'] = 14;
    return $config;
} );

// Bypass lock for super admins
add_filter( 'slswc_drm_should_lock_page_my-plugin', function ( $lock, $drm ) {
    if ( is_super_admin() ) {
        return false;
    }
    return $lock;
}, 10, 2 );

License Lifecycle Hooks

React to license events or modify license behavior:

// Send a webhook when a license is activated.
add_action( 'slswc_license_activated_notification', function ( $license, $domain_data ) {
    wp_remote_post( 'https://example.com/webhook/license-activated', array(
        'body' => wp_json_encode( array(
            'license_key' => $license->get_license_key(),
            'domain'      => $domain_data['domain'] ?? '',
        ) ),
        'headers' => array( 'Content-Type' => 'application/json' ),
    ) );
}, 10, 2 );

// Add custom data to the activation response.
add_filter( 'slswc_activate_result', function ( $result ) {
    $result['support_url'] = 'https://your-store.com/support/';
    return $result;
} );

// Customize the license expiry date calculation.
add_filter( 'slswc_license_expiry', function ( $expiry, $purchase_date ) {
    // Example: always set expiry to end of the year.
    return gmdate( 'Y-12-31', strtotime( $purchase_date ) );
}, 10, 2 );

// Customize license error messages.
add_filter( 'slswc_license_error_message', function ( $message, $error_code ) {
    if ( 'max_activations' === $error_code ) {
        return 'You have reached the maximum number of sites. Please deactivate one first.';
    }
    return $message;
}, 10, 2 );

Subscription Lifecycle Hooks

Hook into subscription state changes to trigger external actions:

// Notify your CRM when a subscription is cancelled.
add_action( 'slswc_subscription_cancelled', function ( $subscription, $gateway, $gateway_sub_id ) {
    my_crm_cancel_subscription( $subscription->customer_id, $gateway_sub_id );
}, 10, 3 );

// Send a custom email when a subscription is about to expire.
add_action( 'slswc_subscription_expiring_notification', function ( $subscription ) {
    wp_mail(
        $subscription->billing_email,
        'Your subscription is expiring soon',
        'Renew now to avoid losing access.'
    );
} );

// Hook into the daily admin summary.
add_action( 'slswc_admin_daily_summary_notification', function ( $summary ) {
    // Forward the summary to a Slack channel, dashboard, etc.
} );

Client Library Request Customization

Customize how your plugin/theme communicates with the license server:

// Increase the timeout for license server requests.
add_filter( 'slswc_request_options_my-plugin', function ( $options ) {
    $options['timeout'] = 60;
    return $options;
} );

// Add extra data to license server requests.
add_filter( 'slswc_request_info_my-plugin', function ( $request_info ) {
    $request_info['site_name'] = get_bloginfo( 'name' );
    return $request_info;
} );

Note: Replace my-plugin with your product's text domain.

Support System Customization

Customize the support ticket system using these hooks:

// Change the ticket number prefix.
add_filter( 'slswc_support_ticket_prefix', function () {
    return 'SUP-';
} );

// Send a Slack notification when a new ticket is created.
add_action( 'slswc_support_ticket_created_admin', function ( $ticket ) {
    wp_remote_post( 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL', array(
        'body' => wp_json_encode( array(
            'text' => sprintf( 'New support ticket: %s', $ticket->title ),
        ) ),
        'headers' => array( 'Content-Type' => 'application/json' ),
    ) );
} );

// Log ticket status changes.
add_action( 'slswc_support_status_changed', function ( $ticket, $new_status ) {
    error_log( sprintf( 'Ticket %d status changed to %s', $ticket->id, $new_status ) );
}, 10, 2 );

// React to ticket assignments.
add_action( 'slswc_support_ticket_assigned', function ( $ticket, $agent_id ) {
    // Notify the agent, update external tracker, etc.
}, 10, 2 );

Available support actions: slswc_support_ticket_created_customer, slswc_support_ticket_created_admin, slswc_support_reply_notification, slswc_support_status_changed, slswc_support_ticket_closed, slswc_support_ticket_assigned, slswc_support_agent_access, slswc_support_agent_invitation.

Environment Detection Override

Override how SLSWC determines staging/development environments:

// Force a specific domain to be treated as staging
add_filter( 'slswc_is_staging', function ( $is_staging, $domain ) {
    if ( strpos( $domain, 'preview.' ) !== false ) {
        return true;
    }
    return $is_staging;
}, 10, 2 );

// Override development detection
add_filter( 'slswc_is_dev', function ( $is_dev, $url, $environment ) {
    if ( defined( 'MY_PLUGIN_IS_DEV' ) && MY_PLUGIN_IS_DEV ) {
        return true;
    }
    return $is_dev;
}, 10, 3 );

WooCommerce Order Integration

Control license behavior during order processing:

// Prevent license deletion when orders are deleted
add_filter( 'slswc_delete_licenses_when_deleting_order', function ( $delete, $order_id ) {
    // Preserve licenses for refunded orders
    $order = wc_get_order( $order_id );
    if ( $order && $order->get_status() === 'refunded' ) {
        return false;
    }
    return $delete;
}, 10, 2 );

// Customize the license key label on orders
add_filter( 'slswc_license_order_item_meta_label', function () {
    return 'Activation Key';
} );

Was this article helpful?