RP Promap Help Article
Set Up the RP Promap Icon Label Suppression Widget on Shopify
Version: 1.0
Product: RP Promap
Recommended setup: Shopify custom.liquid section on the map page
Overview
The RP Promap Icon Label Suppression Widget is a lightweight enhancement for Store Locator result cards and map popups that replaces repetitive text labels with clean icon-based layouts.
It is designed to:
Replace text-heavy field labels with clean icon-based rows.
Create a more modern and compact Store Locator layout.
Hide labels such as Phone Number, Email, Fax, Website, and Opening Hours.
Support both Store Locator result cards and map popup/info-window layouts.
Support Store Locator templates that use duplicated IDs.
Re-apply automatically when search results, filters, or map interactions dynamically reload the locator markup.
The preferred Shopify setup is to add the CSS and JavaScript through a Custom liquid section on the page that contains your RP Promap or Store Locator map.
Recommended Shopify Setup
1. Open the Shopify Theme Editor
From your Shopify admin:
Go to Online Store.
Select Themes.
On your active theme, select Customize.
2. Open the Page That Contains the Map
In the theme editor, use the page selector at the top to open the page where your RP Promap / Store Locator map is displayed.
This is usually a page such as:
Store Locator
Locations
Find a Store
Map
3. Add a Custom Liquid Section
On the map page:
Select Add section.
Choose Custom liquid.
Place the section below the map section when possible.
Paste the widget CSS and script into the Custom liquid field.
Placing the widget below the map helps ensure the locator markup exists before the script performs its first pass.
The widget also includes delayed passes and a mutation observer, so it can still handle dynamically loaded locator results.
Widget Code Placement
Paste the widget in this order:
<style>block first.<script>block second.
Example structure:
<style>
.promap-scasl-label-suppressed,
.promap-scasl-label-text-suppressed {
display: none !important;
}
a.scasl-field.scasl-left-icon,
#scasl-address.scasl-left-icon,
#scasl-phone.scasl-left-icon,
#scasl-email.scasl-left-icon,
#scasl-fax.scasl-left-icon,
#scasl-web.scasl-left-icon,
#scasl-website.scasl-left-icon,
#scasl-opening-hours.scasl-left-icon,
#scasl-hours.scasl-left-icon {
display: inline-flex;
align-items: center;
gap: 6px;
}
a.scasl-field.scasl-left-icon > svg,
#scasl-address.scasl-left-icon > svg,
#scasl-phone.scasl-left-icon > svg,
#scasl-email.scasl-left-icon > svg,
#scasl-fax.scasl-left-icon > svg,
#scasl-web.scasl-left-icon > svg,
#scasl-website.scasl-left-icon > svg,
#scasl-opening-hours.scasl-left-icon > svg,
#scasl-hours.scasl-left-icon > svg {
width: 15px;
height: 15px;
flex: 0 0 auto;
}
.scasl-left-icon svg, .scasl-oh-left-icon svg {
margin-right: 0px;
}
</style>
Do not place the CSS inside the script. The widget is intentionally split into a separate CSS section and JavaScript section so it is easier to copy, inspect, and troubleshoot.
<script>
/*
Promap Widget: Store Locator Icon Fix + Label Suppression
Version: 1.4.1
Purpose
- Fixes Store Locator result-list rows where phone/email/fax/web/opening-hours value lines are missing the correct left icon.
- Suppresses labels in both result-list cards and map popup / info-window cards.
- Handles popup rows where icon, label, and value appear inside the same row.
- Removes incorrect/default icons from result-list data rows before inserting the correct cloned icon.
- Removes any icon accidentally added to Directions links.
- Handles duplicated IDs safely using querySelectorAll instead of getElementById.
Usage
1. Paste the CSS block into your stylesheet or Shopify Custom liquid section.
2. Paste this script after the Store Locator / RP Promap markup or app embed.
3. suppressLabelLine defaults to true.
4. Set suppressLabelLine to false if you want label rows visible.
*/
(function () {
var PromapStoreLocatorIconFix = {
config: {
suppressLabelLine: true,
itemSelector: [
'li.beside-scasl-item',
'li#scasl-list-container',
'#infowindow-wrapper',
'#scasl-window-container',
'.scasl-info-window'
].join(', '),
labelTextSelector: [
'#scasl-phone-label',
'#scasl-email-label',
'#scasl-fax-label',
'#scasl-web-label',
'#scasl-website-label',
'#scasl-oh-label',
'#scasl-opening-hours-label'
].join(', '),
labelRowSelector: '.scasl-field.scasl-left-icon, .scasl-field.left-align-info, .scasl-field',
targetSelector: [
'#scasl-address',
'#scasl-phone',
'#scasl-email',
'#scasl-fax',
'#scasl-web',
'#scasl-website',
'#scasl-opening-hours',
'#scasl-hours',
'a.scasl-field',
'a.align-flex-content',
'a.align-wrap-content',
'a[href^="tel:"]',
'a[href^="mailto:"]',
'a[href^="http://"]',
'a[href^="https://"]',
'.scasl-content'
].join(', '),
fieldMap: [
{
name: 'phone',
labelTexts: ['#scasl-phone-label'],
targets: ['#scasl-phone', 'a[href^="tel:"]'],
hrefPrefixes: ['tel:']
},
{
name: 'email',
labelTexts: ['#scasl-email-label'],
targets: ['#scasl-email', 'a[href^="mailto:"]'],
hrefPrefixes: ['mailto:']
},
{
name: 'fax',
labelTexts: ['#scasl-fax-label'],
targets: ['#scasl-fax', '#scasl-fax .scasl-content'],
hrefPrefixes: []
},
{
name: 'web',
labelTexts: ['#scasl-web-label', '#scasl-website-label'],
targets: ['#scasl-web', '#scasl-website', 'a[href^="http://"]', 'a[href^="https://"]'],
hrefPrefixes: ['http://', 'https://']
},
{
name: 'opening-hours',
labelTexts: ['#scasl-oh-label', '#scasl-opening-hours-label'],
targets: ['#scasl-opening-hours', '#scasl-hours', '#scasl-opening-hours .scasl-content', '#scasl-hours .scasl-content'],
hrefPrefixes: []
}
],
suppressedClass: 'promap-scasl-label-suppressed',
suppressedTextClass: 'promap-scasl-label-text-suppressed',
patchedClass: 'promap-scasl-icon-patched'
},
matches: function (element, selector) {
if (!element || !selector) return false;
var proto = Element.prototype;
var fn = proto.matches || proto.msMatchesSelector || proto.webkitMatchesSelector;
return fn.call(element, selector);
},
closest: function (element, selector) {
if (!element || !selector) return null;
if (element.closest) return element.closest(selector);
while (element && element.nodeType === 1) {
if (this.matches(element, selector)) return element;
element = element.parentElement;
}
return null;
},
queryAll: function (root, selectors) {
if (!root || !selectors) return [];
var selector = Array.isArray(selectors) ? selectors.join(', ') : selectors;
if (!selector) return [];
return Array.prototype.slice.call(root.querySelectorAll(selector));
},
getHref: function (element) {
return ((element && element.getAttribute && element.getAttribute('href')) || '').toLowerCase().trim();
},
hasHrefPrefix: function (element, prefixes) {
var href = this.getHref(element);
if (!href || !prefixes || !prefixes.length) return false;
return prefixes.some(function (prefix) {
return href.indexOf(prefix) === 0;
});
},
hasPatchableHref: function (anchor) {
return this.hasHrefPrefix(anchor, ['tel:', 'mailto:', 'http://', 'https://']);
},
isDirectionTarget: function (target) {
return !!(
target &&
(
target.id === 'scasl-direction' ||
(target.closest && target.closest('#scasl-direction'))
)
);
},
removeDirectionIcons: function () {
var rows = document.querySelectorAll('#scasl-direction');
Array.prototype.slice.call(rows).forEach(function (row) {
var links = Array.prototype.slice.call(row.querySelectorAll('a'));
links.forEach(function (link) {
var svgs = Array.prototype.slice.call(link.querySelectorAll('svg'));
svgs.forEach(function (svg) {
if (svg.parentNode) svg.parentNode.removeChild(svg);
});
link.classList.remove('scasl-left-icon');
link.classList.remove('promap-scasl-icon-patched');
});
});
},
getDirectSvgFromRow: function (row) {
if (!row) return null;
var children = Array.prototype.slice.call(row.children || []);
for (var i = 0; i < children.length; i += 1) {
if (children[i].tagName && children[i].tagName.toLowerCase() === 'svg') {
return children[i];
}
}
return row.querySelector('svg');
},
getSvgCloneFromLabelRow: function (labelRow) {
var svg = this.getDirectSvgFromRow(labelRow);
return svg ? svg.cloneNode(true) : null;
},
removeSvgsFromElement: function (element) {
if (!element || !element.querySelectorAll) return;
var svgs = Array.prototype.slice.call(element.querySelectorAll('svg'));
svgs.forEach(function (svg) {
if (svg.parentNode) svg.parentNode.removeChild(svg);
});
},
isInlinePopupLabelRow: function (labelRow) {
if (!labelRow) return false;
var hasLabel = !!labelRow.querySelector(this.config.labelTextSelector);
var hasValue = !!labelRow.querySelector([
'a[href^="tel:"]',
'a[href^="mailto:"]',
'a[href^="http://"]',
'a[href^="https://"]',
'a.align-flex-content',
'a.align-wrap-content',
'.scasl-content'
].join(', '));
return hasLabel && hasValue;
},
suppressLabelTextsInRow: function (labelRow) {
var self = this;
var labelTexts = this.queryAll(labelRow, this.config.labelTextSelector);
labelTexts.forEach(function (labelText) {
if (self.config.suppressLabelLine) {
labelText.classList.add(self.config.suppressedTextClass);
labelText.setAttribute('aria-hidden', 'true');
labelText.style.display = 'none';
} else {
labelText.classList.remove(self.config.suppressedTextClass);
labelText.removeAttribute('aria-hidden');
labelText.style.display = '';
}
});
},
suppressLabelRow: function (labelRow) {
if (!labelRow) return;
this.suppressLabelTextsInRow(labelRow);
if (this.isInlinePopupLabelRow(labelRow)) {
labelRow.classList.remove(this.config.suppressedClass);
labelRow.removeAttribute('aria-hidden');
labelRow.style.display = '';
return;
}
if (this.config.suppressLabelLine) {
labelRow.classList.add(this.config.suppressedClass);
labelRow.setAttribute('aria-hidden', 'true');
labelRow.style.display = 'none';
} else {
labelRow.classList.remove(this.config.suppressedClass);
labelRow.removeAttribute('aria-hidden');
labelRow.style.display = '';
}
},
suppressAllConfiguredLabels: function (item) {
var self = this;
var labelTexts = this.queryAll(item, this.config.labelTextSelector);
labelTexts.forEach(function (labelText) {
var labelRow = self.closest(labelText, self.config.labelRowSelector) || labelText.parentElement;
self.suppressLabelRow(labelRow);
});
},
isLabelRow: function (element) {
if (!element || !element.querySelector) return false;
return !!element.querySelector(this.config.labelTextSelector);
},
isValueTarget: function (target, field) {
if (!target) return false;
if (this.isDirectionTarget(target)) return false;
if (this.isLabelRow(target) && !this.isInlinePopupLabelRow(target)) return false;
if (field && this.hasHrefPrefix(target, field.hrefPrefixes)) return true;
if (target.tagName && target.tagName.toLowerCase() === 'a' && this.hasPatchableHref(target)) return true;
if (target.id && /^(scasl-address|scasl-phone|scasl-email|scasl-fax|scasl-web|scasl-website|scasl-opening-hours|scasl-hours)$/.test(target.id)) {
return true;
}
return false;
},
findLabelRowsForField: function (item, field) {
var self = this;
var labelTexts = this.queryAll(item, field.labelTexts || []);
return labelTexts.map(function (labelText) {
return self.closest(labelText, self.config.labelRowSelector) || labelText.parentElement;
}).filter(function (row, index, rows) {
return row && rows.indexOf(row) === index;
});
},
patchInlinePopupRow: function (labelRow) {
if (!labelRow || !this.isInlinePopupLabelRow(labelRow)) return;
labelRow.classList.add('scasl-left-icon');
labelRow.classList.add(this.config.patchedClass);
this.suppressLabelRow(labelRow);
},
patchTargetWithLabelRow: function (target, labelRow, field) {
if (!target || !labelRow) return;
if (this.isDirectionTarget(target)) return;
if (this.isInlinePopupLabelRow(labelRow)) {
this.patchInlinePopupRow(labelRow);
return;
}
if (!this.isValueTarget(target, field)) return;
var svg = this.getSvgCloneFromLabelRow(labelRow);
if (!svg) {
this.suppressLabelRow(labelRow);
return;
}
this.removeSvgsFromElement(target);
target.classList.add('scasl-left-icon');
target.classList.add(this.config.patchedClass);
target.insertBefore(svg, target.firstChild);
this.removeSvgsFromElement(labelRow);
this.suppressLabelRow(labelRow);
},
patchMappedFields: function (item) {
var self = this;
this.config.fieldMap.forEach(function (field) {
var labelRows = self.findLabelRowsForField(item, field);
var targets = self.queryAll(item, field.targets).filter(function (target) {
return !self.isDirectionTarget(target);
});
if (!labelRows.length) return;
labelRows.forEach(function (labelRow) {
if (self.isInlinePopupLabelRow(labelRow)) {
self.patchInlinePopupRow(labelRow);
}
});
if (!targets.length) return;
targets.forEach(function (target, index) {
var labelRow = labelRows[index] || labelRows[0];
self.patchTargetWithLabelRow(target, labelRow, field);
});
});
},
patchStructuralGroups: function (item) {
var self = this;
var groups = item.querySelectorAll('div, .left-align-info, .scasl-content, .align-flex-content');
groups.forEach(function (group) {
var labelText = group.querySelector(self.config.labelTextSelector);
if (!labelText) return;
var labelRow = self.closest(labelText, self.config.labelRowSelector) || labelText.parentElement;
if (!labelRow) return;
if (self.isInlinePopupLabelRow(labelRow)) {
self.patchInlinePopupRow(labelRow);
return;
}
var targets = self.queryAll(group, self.config.targetSelector).filter(function (target) {
return target !== labelRow && !labelRow.contains(target) && !self.isLabelRow(target) && !self.isDirectionTarget(target);
});
targets.forEach(function (target) {
self.patchTargetWithLabelRow(target, labelRow, null);
});
});
},
patchItem: function (item) {
this.patchMappedFields(item);
this.patchStructuralGroups(item);
this.suppressAllConfiguredLabels(item);
},
patchAll: function () {
var items = document.querySelectorAll(this.config.itemSelector);
var self = this;
items.forEach(function (item) {
self.patchItem(item);
});
this.removeDirectionIcons();
},
observe: function () {
var self = this;
var observer = new MutationObserver(function () {
self.patchAll();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
},
init: function (options) {
this.config = Object.assign({}, this.config, options || {});
this.patchAll();
this.observe();
var self = this;
setTimeout(function () { self.patchAll(); }, 500);
setTimeout(function () { self.patchAll(); }, 1500);
}
};
window.PromapStoreLocatorIconFix = PromapStoreLocatorIconFix;
PromapStoreLocatorIconFix.init({
suppressLabelLine: true
});
})();
</script>
Default Icon-First Layout Behavior
The widget is configured to suppress label rows by default:
suppressLabelLine: true
With this enabled, labels such as Phone Number, Email, Fax, Website, and Opening Hours are hidden after the correct icon is moved to the data line.
For example, instead of displaying:
Phone Number (620) 670-9723
The card displays:
[phone icon] (620) 670-9723
Optional: Keep Text Labels Visible
To keep the label rows visible, change the setting at the bottom of the script:
suppressLabelLine: false
This keeps the label/header row visible while still correcting icons on the data row.
Most Shopify Store Locator layouts should leave this set to:
suppressLabelLine: true
What the Widget Enhances
The widget targets common Store Locator field wrappers and value rows, including:
Field Wrapper Classes
.scasl-field .scasl-left-icon .left-align-info .scasl-content .align-flex-content
Supported Value IDs
#scasl-address #scasl-phone #scasl-email #scasl-fax #scasl-web #scasl-website #scasl-opening-hours #scasl-hours
Supported Label IDs
#scasl-phone-label #scasl-email-label #scasl-fax-label #scasl-web-label #scasl-website-label #scasl-oh-label #scasl-opening-hours-label
Some Store Locator templates use the same ID more than once in a result card. This is not standard HTML, but the widget is designed to handle that pattern safely by using selector-based matching instead of getElementById.
Testing the Setup
After saving the Custom liquid section:
Open the Store Locator page on the storefront.
Search for a location that includes phone, email, website, fax, or hours fields.
Confirm the correct icon appears on the data line.
Confirm label text such as Phone Number is hidden.
Use search, filter, or map interactions to reload results.
Confirm the fix remains applied after the results refresh.
Example Image with Labels Suppressed
Troubleshooting
The labels are still showing
Confirm the CSS block was pasted above the script and includes:
.promap-scasl-label-suppressed, .promap-scasl-label-text-suppressed { display: none !important; }The script also applies an inline display: none fallback when suppressLabelLine is set to true.
The wrong icon is showing
Confirm you are using the latest widget version. The script should remove existing/default SVGs from the data row before inserting the correct cloned icon from the label row.
The widget works at first but breaks after filtering or searching
The widget includes a MutationObserver and delayed re-apply passes for dynamic Store Locator rendering.
If the issue only appears after interactions, make sure the script is placed on the same page as the map and is not blocked by theme optimization, app embed settings, or script deferral.
Nothing changes on the storefront
Check the following:
The Custom liquid section is on the correct page template.
The section was saved and published.
The widget appears after the map or Store Locator section.
The browser cache or Shopify preview cache has been refreshed.
The Store Locator markup uses the supported selectors listed above.
Recommended Maintenance
Keep the widget code together in one Custom liquid section on the map page. This makes it easier to update, disable, or remove later.
When updating the widget, replace both the CSS and script blocks at the same time to avoid version mismatches.
Recommended RP Promap Setup
The recommended setup is:
Open the Shopify theme editor.
Go to the page with the RP Promap / Store Locator map.
Add a Custom liquid section below the map.
Paste the widget CSS first, then the script.
Leave
suppressLabelLine: trueunless label rows should remain visible.Save and test the locator results on the storefront.
This setup keeps the fix page-specific, easy to maintain, and separate from the main theme code.
© Rose Perl Technology

