With the SaaS dashboard there is a Manage | Customers option that displays the customer list. It is using a default WordPress table style presentation that has been modified by one of the SaaS plugins, most likely MySLP Dashboard (myslp-dashboard). I would like to make improvements to this interface.
Twenty Twelve Theme Does Not Exist
Theme “twenty twelve does not exist” ranger creek categories
Sadly, some of the accounts like “ranger_creek” are not longer available and are not able to show the issue. It is difficult finding which accounts reproduce the errors and where.
Canceling Account Immediate Expires Map
A user canceled their account. The website immediate showed the SLP maps as expired instead of checking the renewal/expiration date.
Reproduction
E2E Steps
- Login as professional@storelocatorplus.com
- Make sure the account is active
- Go to My Profile by clicking “My Profile” in the admin sidebar
xpath=//*[@id=”toplevel_page_myslp_profile”] - Affirm there is a Cancel Subscription button on the page
xpath=//*[@data-cy=”cancel-subscription-button”]
- Go to My Profile by clicking “My Profile” in the admin sidebar
- Click the Cancel Subscription button
- Go to Generate Embed by clicking “Generate Embed” in the admin sidebar
xpath=//*[@id=”toplevel_page_admin-page-myslp-dashboard-tab-deployment”]
If the account still has time left on the subscription.
The map display area on the Generate Embed page should not show the text “This Store Locator Plus® account has expired.”
Cancelling Subscription Creates New Subscription
I had to update the stripe connection which meant rewriting how subscription processing is managed including cancellations.
So for the customer mcampbell_at_tnwebtech_dot_com (830.828) this is what I have as the status:
original subscription 24th
last renewed feb 24th
cancelled mar 6th
stripe charged them mar 6th AND marked it cancelled april 6th
it should have marked the 24th subscription to cancel on mar 24th
Clearly a bug in the new cancellation processor.
Task: https://github.com/Store-Locator-Plus/myslp_aws_ecs_kit/issues/94
Dev Notes
Customer: mc…tnwebtech… (830.828)
customer: mcampbell@tnwebtech.com
Current status according to Stripe: they have set their account to cancel on April 5th
Current subscription: *z8ku is deleted on Stripe now meaning it will not auto-renew
Please ensure that is what they want.
From the Stripe history:
The original subscription *9h4z
Started Oct 24 2023
Cancelled via SLP Dashboard on Mar 6th 2026 at 1:05AM (server time)
Was set to stop providing SLP maps on Mar 24th 2026
They then renewed (created the new subscription) Mar 6th at 1:08AM (server time)
This is set to expire on April 5th 2026
Yes, we have an issue with RENEW
If the prior subscription is still active (*9h4z in this case) it should set the new subscription (renewal) to start when that ends (Mar 24th 2026 06:21AM server time)
The bug is that is started immediately , thus the new 6th to 5th dates
That is OK for renewals that happen AFTER the maps are disabled (most users) but in this unique situation it needs to be addressed.
Stripe
Current Subscription *z8ku
Started and cancelled March 6th 2026
Mar 6, 2026, 1:08:53 AM EDT POST/v1/subscriptions
{
"id": "sub_1T7rZBBvHKfBw2LGODU6z8ku",
"object": "subscription",
...
"cancel_at": null,
"cancel_at_period_end": false,
"canceled_at": null,
"cancellation_details": {
"comment": null,
"feedback": null,
"reason": null,
},
"collection_method": "charge_automatically",
"created": 1772777333,
"currency": "usd",
"current_period_end": 1775455733, // April 5 2026 06:22:13
"current_period_start": 1772777333,
"customer": "cus_OsOnxeaYjgqPNu",
...
"items": {
"object": "list",
"data": [
{
"id": "si_U63gr60piiTUmH",
"object": "subscription_item",
"billing_thresholds": null,
"created": 1772777334,
"current_period_end": 1775455733,
"current_period_start": 1772777333,
"discounts": [],
"metadata": {},
"plan": {
"id": "Professional",
"object": "plan",
"active": true,
"aggregate_usage": null,
"amount": 3500,
"amount_decimal": "3500",
"billing_scheme": "per_unit",
"created": 1500935159,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": true,
"metadata": {},
"meter": null,
"nickname": null,
"product": "prod_BU6KhAFcwnXTef",
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"price": {
"id": "Professional",
"object": "price",
"active": true,
"billing_scheme": "per_unit",
"created": 1500935159,
"currency": "usd",
"custom_unit_amount": null,
"livemode": true,
"lookup_key": null,
"metadata": {},
"nickname": null,
"product": "prod_BU6KhAFcwnXTef",
"recurring": {
"aggregate_usage": null,
"interval": "month",
"interval_count": 1,
"meter": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"tax_behavior": "unspecified",
"tiers_mode": null,
"transform_quantity": null,
"type": "recurring",
"unit_amount": 3500,
"unit_amount_decimal": "3500"
},
"quantity": 1,
"subscription": "sub_1T7rZBBvHKfBw2LGODU6z8ku",
"tax_rates": []
}
],
...
},
...
"trial_settings": {
"end_behavior": {
"missing_payment_method": "create_invoice"
}
},
"trial_start": null
}
Mar 6, 2026, 1:09:11 AM EDT POST /v1/subscriptions/sub_1T7rZBBvHKfBw2LGODU6z8ku
{
"id": "sub_1T7rZBBvHKfBw2LGODU6z8ku",
"object": "subscription",
...
"cancel_at": 1775455733,
"cancel_at_period_end": true,
"canceled_at": 1772777351,
"cancellation_details": {
"comment": null,
"feedback": null,
"reason": "cancellation_requested"
},
"collection_method": "charge_automatically",
"created": 1772777333,
"currency": "usd",
"current_period_end": 1775455733,
"current_period_start": 1772777333,
"customer": "cus_OsOnxeaYjgqPNu",
...
}
Mar 6, 2026, 1:09:12 AM EDT DELETE/v1/subscriptions/sub_1T7rZBBvHKfBw2LGODU6z8ku

Original Subscription: *h4z
Started: 2023-10-24
Ended: 2026-03-06 01:05AM
Mar 6, 2026, 1:05:04 AM EDT POST/v1/subscriptions/sub_1O4dzSBvHKfBw2LGsKZp9h4z
{
"id": "sub_1O4dzSBvHKfBw2LGsKZp9h4z",
"object": "subscription",
"application": null,
"application_fee_percent": null,
"automatic_tax": {
"disabled_reason": null,
"enabled": false,
"liability": null
},
"billing_cycle_anchor": 1698128482,
"billing_cycle_anchor_config": null,
"billing_mode": {
"flexible": null,
"type": "classic"
},
"billing_thresholds": null,
"cancel_at": 1774333282, // Mar 24 2026 06:21:22 AM (correct)
"cancel_at_period_end": true,
"canceled_at": 1772777104, // Mar 6 2026 01:05:04 AM
"cancellation_details": {
"comment": null,
"feedback": null,
"reason": "cancellation_requested"
},
"collection_method": "charge_automatically",
"created": 1698128482,
"currency": "usd",
"current_period_end": 1774333282, // Mar 24 2026 06:21:22 AM (correct)
"current_period_start": 1771914082, // February 23 2026 11:21:22 PM
"customer": "cus_OsOnxeaYjgqPNu",
"customer_account": null,
"days_until_due": null,
"default_payment_method": null,
"default_source": null,
"default_tax_rates": [],
"description": null,
"discount": null,
"discounts": [],
"ended_at": null,
"invoice_settings": {
"account_tax_ids": null,
"issuer": {
"type": "self"
}
},
"items": {
"object": "list",
"data": [
{
"id": "si_OsOnhVkp9iBCCb",
"object": "subscription_item",
"billing_thresholds": null,
"created": 1698128483,
"current_period_end": 1774333282,
"current_period_start": 1771914082,
"discounts": [],
"metadata": {},
"plan": {
"id": "Professional",
"object": "plan",
"active": true,
"aggregate_usage": null,
"amount": 3500,
"amount_decimal": "3500",
"billing_scheme": "per_unit",
"created": 1500935159,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": true,
"metadata": {},
"meter": null,
"nickname": null,
"product": "prod_BU6KhAFcwnXTef",
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"price": {
"id": "Professional",
"object": "price",
"active": true,
"billing_scheme": "per_unit",
"created": 1500935159,
"currency": "usd",
"custom_unit_amount": null,
"livemode": true,
"lookup_key": null,
"metadata": {},
"nickname": null,
"product": "prod_BU6KhAFcwnXTef",
"recurring": {
"aggregate_usage": null,
"interval": "month",
"interval_count": 1,
"meter": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"tax_behavior": "unspecified",
"tiers_mode": null,
"transform_quantity": null,
"type": "recurring",
"unit_amount": 3500,
"unit_amount_decimal": "3500"
},
"quantity": 1,
"subscription": "sub_1O4dzSBvHKfBw2LGsKZp9h4z",
"tax_rates": []
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/subscription_items?subscription=sub_1O4dzSBvHKfBw2LGsKZp9h4z"
},
"latest_invoice": "in_1T4EzzBvHKfBw2LGXjuYItOu",
"livemode": true,
"metadata": {},
"next_pending_invoice_item_invoice": null,
"on_behalf_of": null,
"pause_collection": null,
"payment_settings": {
"payment_method_options": null,
"payment_method_types": null,
"save_default_payment_method": null
},
"pending_invoice_item_interval": null,
"pending_setup_intent": null,
"pending_update": null,
"plan": {
"id": "Professional",
"object": "plan",
"active": true,
"aggregate_usage": null,
"amount": 3500,
"amount_decimal": "3500",
"billing_scheme": "per_unit",
"created": 1500935159,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": true,
"metadata": {},
"meter": null,
"nickname": null,
"product": "prod_BU6KhAFcwnXTef",
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"quantity": 1,
"schedule": null,
"start_date": 1698128482,
"status": "active",
"test_clock": null,
"transfer_data": null,
"trial_end": null,
"trial_settings": {
"end_behavior": {
"missing_payment_method": "create_invoice"
}
},
"trial_start": null
}
Mar 6, 2026, 1:05:05 AM EDT DELETE/v1/subscriptions/sub_1O4dzSBvHKfBw2LGsKZp9h4z
SLP SaaS
Currently on Professional Plan
Expires 2026-05-21 06:08:53
Cancelled 2026-03-06 06:09:11
Current Stripe subscription: sub_1T7rZBBvHKfBw2LGODU6z8ku

Stripe Notes
Currently using Classic billing mode.
Flexible Recommended: Provides accurate and predictable billing behavior and new capabilities. To access these improvements, which are only available in flexible billing mode, you must create new subscriptions with flexible billing mode or migrate your existing subscriptions.
*Classic: Uses the existing Stripe subscription behavior. This setting is maintained for backward compatibility with older integrations.
AI Resolution Assistance
Prompt
@Amelia -
In the MySLP Payments module (WordPress/wp-content/plugins/myslp-payments) there is an issue related to renewing cancelled subscriptions.
__
Make a note of this as general knowledge about the Store Locator Plus Saas Application:
- local (https://local.storelocatorplus.com) and staging (https://staging.storelocatorplus.com) servers may be using outdated data sets
- local and staging servers employ the Stripe TEST environment and related keys
- the production server uses live keys
- NEVER run tests against live Stripe customer data using live keys even on the staging or local servers
__
The following scenario is a real-world situation which played out on the production version of the SaaS application.
We have an issue with RENEW subscription.
- If the prior subscription is still active (sub_1O4dzSBvHKfBw2LGsKZp9h4z in this case) it should set the new subscription (sub_1T7rZBBvHKfBw2LGODU6z8ku) to start when the still-active subscription ends (Mar 24th 2026 06:21AM server time).
- The bug is that the new subscription started immediately setting a March 6th start date when an April 5th end date.
- The new subscription should have started on March 24th 2026 at 6:21AM.
- If the prior subscription is past the end (cancel_at) date, only then should the renewal start immediately. That was not the case in this situation.
Meta data about the customer and their interaction with the application:
customer: mcampbell@tnwebtech.com
Current status according to Stripe: they have set their account to cancel on April 5th
Current subscription: *z8ku is deleted on Stripe now meaning it will not auto-renew
Please ensure that is what they want.
From the Stripe history:
The original subscription *9h4z
Started Oct 24 2023
Cancelled via SLP Dashboard on Mar 6th 2026 at 1:05AM (server time)
Was set to stop providing SLP maps on Mar 24th 2026
They then renewed (created the new subscription) Mar 6th at 1:08AM (server time)
This is set to expire on April 5th 2026
AI Fix
in \stripe\MySLP_Stripe_Payments::renew_subscription add the trial_end argument.
// If the old subscription still has remaining paid time, defer the new
// subscription so it starts when the old period ends.
$prior_period_end = $this->subscription->current_period_end ?? null;
if ( $prior_period_end && $prior_period_end > time() ) {
$args['trial_end'] = $prior_period_end;
}
try {
$this->subscription = Subscription::create( $args );
E2E Testing
Write a new E2E Test Specification "subscription_renewals".
The first test in the specification needs to test "Can renew a subscription before it has expired".
This is a corner case with some specific requirements.
- Login as a user with a current active subscription
- Go to My Profile and look for the current subscription ID, remember this value
- Go to My Profile and cancel the subscription
-- The current Stripe subscription ID should be posted and marked in Stripe as canceled
-- The current subscription should have a cancellation date at the end of the current period
- Go to My Profile and renew the subscription
-- This should create a new Stripe subscription ID
-- The new Stripe subscription ID should start when the current period ends
-- The new Stripe subscription should NOT start at the date/time of the renewal
-- The new Stripe subscription should be set to renew in a month (current period ends a month later)
Update SLP_Country_Manager To Include All Regions
Contains the map and other data that drives SLP for each country.
ccTLD is the region parameter for Google Maps
ccTLD is any of the Unicode region subtag identifiers
See https://developers.google.com/maps/coverage for a list of supported regions, 2D/3D map tiles apply here
\SLP_Country_Manager::load_country_data sets up the list of country meta data for this purpose.
It has not been updated since 2018.
Map Center Fallback Not Rendering Map
Under Settings | Map the map center fallback is not rendering the map.

Settings ID: center_map
This is a Premier feature.
May be related to Google Maps and SLP Core script enqueue
Map Bubble Description Format (Default Style)
Went to locator styles: default and selected it to get the baseline form the style server first.
The map bubble description format is not retaining whitespace (returns) with the default style.


My Profile | Subscription | Update Card
The pre-production release of the 2602.XX.YY versions of the SaaS are setup with a revised React-based subscription processor.
The My Profile | Subscription tab allows the user to…
- Change the plan (upgrade, downgrade)
- Update Card
- Cancel Subscription
Update Card
The update card process appears to be calling the backend, however how Stripe stores payment data and how it is rendered has changed.
Contact Us Loading On Every Page
When a user is logged in, the application stack is calling \MySLP_Contact_Us::initialize on every page load on the MySLP SaaS system. This should only be loaded when a user is interacting with the Contact Us page in the app.
This is being called via \MySLP_loader in the myslp-dashboard code. This happens when plugins_loaded action hooks are called from WordPress per this code block:
// Load the Customer Profile module AFTER history logger (pri; 15)
add_action( 'plugins_loaded', function () {
/**
* @return void
*/
function myslp_customer_interfaces_loader(): void {
require_once( MYSLP_PLUGIN_DIR . 'include/customer_profile/MySLP_Customer_Profile.php' );
require_once( MYSLP_PLUGIN_DIR . 'include/MySLP_Contact_Us.php' );
require_once( MYSLP_PLUGIN_DIR . 'include/MySLP_Customer_Maintenance.php' );
MySLP_Contact_Us::get_instance();
}
myslp_customer_interfaces_loader();
}, 15 );
My Profile | Notifications
The My Profile page is rendered as a React component as of the 2601.XX release. This is invoke using the WordPress blocks system via the JavaScript wp scripts helper in package.json.
Related PHP Classes and Methods
My Profile is managed via the MySLP Dashboard repo (Store-Locator-Plus/myslp-dashboard).
The \MySLP_Customer_Profile class extends SLP_Base_ReactObject.
SLP_Base_ReactObject is the Store Locator Plus class that acts as the helper to wire PHP data to the JavaScript interface using the defined WordPress blocks system. WordPress blocks are , at their core, React components.
SLP_Base_ReactObject JavaScript Variable Population
This is handled via the extendReactVars method, which is usually extended by child classes.
The return PHP array end up populating the slpReact JavaScript variable.
Most of the MySLP (SaaS code) variables will return a sub-array named mySLP.
This results in the JavaScript variable slpReact.mySLP which contains SaaS specific variables.
For example:
$vars[‘mySLP’][‘subscription’] = $this->get_subscription_data();
The notifications stack uses the MySLP_Customer_Profile::add_notification to build an array of notification messages. These are then consumed by the React ProfilePanel component.
Related React Components
ProfilePanel in WordPress/wp-content/plugins/myslp-dashboard/src/profile/profile.tsx is the primary wrapper for the entire My Profile page React component.
Notifications are handled by a Snackbar component provided by the @mui/material React framework.
It is driven by the JavaScript variables slpReact.mySLP.notifications array.
Each element is an object with a message<string> and severity<string> property.
If the notifications array is not empty, the Snackbar opens and the message stack is displayed.
The severity element defines the style of the Snackbar message interface.
My Profile | Cancel Subscription Not Working
This is an issue with the updates to the My Profile interface from the 2602.01.01 version of the SLP SaaS platform.
Going to My Profile | Cancel Subscription is no longer working. It appears to post to the backend for processing, but there is not notification of cancellation and there is no update to the status.

Foreach loop null attributes in SLP_UI_Shortcode_slp_option.php
When testing generate embed for “Freshy” the JS dev tools throws a warning:
[Log] (location.js, line 190)
Warning: foreach() argument must be of type array|object, null given in /var/www/html/wp-content/mu-plugins/store-locator-plus/include/module/ui/SLP_UI_Shortcode_slp_option.php on line 94
As per Foreach loop in SLP_UI_Shortcode_slp_option.php#69