Option to pre-select filters

Is there a way to pre-set the filters on the store locator widget based on URL? For example, if on the nutrition page of my website i want to be able to allow users to pick a state, then pass that through the URL to see a list of locations to get scheduled rather than going to the store locator, and having to first filter by state and then by nutrition to find the nutrition locations. I am trying to reduce clicks

Example - in this screenshot image the schedule now button can pass the category filter parameter through the URL so it can take users to the locations page and be pre-filtered for the nutrition service

2 Likes

Hi there, @Info_at_BEST :waving_hand:

Could you please send me a list of the URLs with the filters you’d like to pre-select for each page? I’ll gladly check what can be done :wink:

1 Like

I need the URL below + whatever you need appended to the URL so that it can filter by my categories https://besthwp.com/locations.html

something like the below would be ideal:
https://besthwp.com/locations.html#nutrition - would filter the locations/stores to just the ones with the locations with the Nutrition category

https://besthwp.com/locations.html#physical-therapy - would filter the locations/stores to just the ones with the locations with the Physical Therapy category

https://besthwp.com/locations.html#behavioral-health - would filter the locations/stores to just the ones with the locations with the Behavioral Health category

Here are my categories

2 Likes

Ah, I see, you just need to assign the service attribute to the page URL when choosing them in the filter. Thanks for clarification!

Would you like to apply this behavior to the State filter as well?

1 Like

If possible that would be amazing!

the main problem I am trying to solve is i want to change the Schedule Now button on this page of my website (https://besthwp.com/nc_services.html) - to take users to the locations page and be pre-filtered for nutrition. The idea is to update that “Schedule Now” button to be “https://besthwp.com/locations.html#nutrition” So they can easily see all the nutrition locations and select the one they want to schedule at. I am worried just taking users to the locations page with all services (navigating from the nutrition page will be confusing). And then having the ability to do that for all our service offerings is fantastic.

Our Nutrition EMR does not allow us to show locations when scheduling so I need to push users to our locations page first so they dont book appointments with a dietitian in a different state by mistake!

2 Likes

Got it!

I’ve forwarded your request to the devs and will report back once it’s done :slightly_smiling_face:

1 Like

Hi there, @Info_at_BEST :waving_hand:

We’ve added this script to the Custom JS field on the Settings tab of your widget’s settings:

const WIDGET_ID = 'b5800a68-c2d2-4ab5-b417-88729ac29380';

const statesFilter = new Set();
const servicesFilter = new Set();
const bufferStatesFilters = new Set();
const bufferServicesFilters = new Set();

let selectedFilter = '';
let isFiltersLoaded = false;

const getSetFromURL = (paramName) => {
	const params = new URLSearchParams(window.location.search);
	const value = params.get(paramName);

	if (!value) return new Set();

	return new Set(value.split(',').map(decodeURIComponent).filter(Boolean));
};

const setToParam = (set) => [...set].map(encodeURIComponent).join(',');

const updateURL = () => {
	const params = new URLSearchParams(window.location.search);

	if (statesFilter.size) {
		params.set('states', setToParam(statesFilter));
	} else {
		params.delete('states');
	}

	if (servicesFilter.size) {
		params.set('services', setToParam(servicesFilter));
	} else {
		params.delete('services');
	}

	const newUrl = `${window.location.pathname}?${params.toString()}`;
	window.history.replaceState(null, '', newUrl);
};

const addFilterHandler = () => {
	const filterButtons = document.querySelectorAll(
		`.elfsight-app-${WIDGET_ID} .es-filters-tag-wrapper:not(:nth-child(3)) > [class*="filter-dropdown__Wrapper-sc"] > button`
	);

	if (!filterButtons.length) {
		setTimeout(addFilterHandler, 250);
		return;
	}

	getSetFromURL('states').forEach((v) => statesFilter.add(v));
	getSetFromURL('services').forEach((v) => servicesFilter.add(v));

	if (statesFilter.size) {
		filterButtons[0].click();

		requestAnimationFrame(() => {
			const dropdown = document.querySelector(
				`.elfsight-app-${WIDGET_ID} [class*="filter-dropdown__Content-sc"]`
			);
			const showMoreButton = dropdown.querySelector(
				'.es-more-less-button-button'
			);
			showMoreButton?.click();

			requestAnimationFrame(() => {
				const allFilterButtons = dropdown.querySelectorAll(
					'[class*="tags-group__TagsGroup-sc"] > button'
				);

				allFilterButtons.forEach((button) => {
					const text = button.querySelector('span').textContent.trim();

					if (statesFilter.has(text)) {
						button.click();
					}
				});

				const applyButton = dropdown.querySelector(
					'.es-apply-filters-button-button'
				);
				requestAnimationFrame(() => applyButton.click());
			});
		});
	}

	if (servicesFilter.size) {
		setTimeout(() => {
			filterButtons[1].click();

			requestAnimationFrame(() => {
				const dropdown = document.querySelector(
					`.elfsight-app-${WIDGET_ID} [class*="filter-dropdown__Content-sc"]`
				);
				const showMoreButton = dropdown.querySelector(
					'.es-more-less-button-button'
				);
				showMoreButton?.click();

				requestAnimationFrame(() => {
					const allFilterButtons = dropdown.querySelectorAll(
						'[class*="tags-group__TagsGroup-sc"] > button'
					);

					allFilterButtons.forEach((button) => {
						const text = button.querySelector('span').textContent.trim();

						if (servicesFilter.has(text)) {
							button.click();
						}
					});

					const applyButton = dropdown.querySelector(
						'.es-apply-filters-button-button'
					);
					requestAnimationFrame(() => applyButton.click());
				});
			});
		}, 500);
	}

	setTimeout(() => {
		isFiltersLoaded = true;
	}, 1000);
};

addFilterHandler();

// Clear buffer
window.addEventListener(
	'click',
	(event) => {
		const dropdown = event.target.closest(
			'[class*="filter-dropdown__Content-sc"]'
		);

		if (!dropdown) {
			bufferStatesFilters.clear();
			bufferServicesFilters.clear();
			selectedFilter = '';
		}
	},
	true
);

// Select filter
window.addEventListener('click', (event) => {
	const filterButton = event.target.closest(
		'.es-filters-tag-wrapper:not(:nth-child(3)) [class*="filter-dropdown__Wrapper-sc"] > button'
	);

	if (!filterButton) {
		return;
	}

	const buttons = [
		...document.querySelectorAll(
			'.es-filters-tag-wrapper:not(:nth-child(3)) [class*="filter-dropdown__Wrapper-sc"] > button'
		),
	];
	const isFirstButton = buttons[0] === filterButton;

	if (isFirstButton) {
		bufferStatesFilters.clear();
		statesFilter.forEach((v) => bufferStatesFilters.add(v));
		selectedFilter = 'States';
	} else {
		bufferServicesFilters.clear();
		servicesFilter.forEach((v) => bufferServicesFilters.add(v));
		selectedFilter = 'Services';
	}
});

// Clear all filters
window.addEventListener(
	'click',
	(event) => {
		const clearButton = event.target.closest(
			'.es-filters-wrapper > .es-clear-filters-button-button'
		);

		if (!clearButton) {
			return;
		}

		statesFilter.clear();
		bufferStatesFilters.clear();
		servicesFilter.clear();
		bufferServicesFilters.clear();

		updateURL();
	},
	true
);

// Clear filters
window.addEventListener(
	'click',
	(event) => {
		const clearButton = event.target.closest('.es-clear-filters-button-button');

		if (!clearButton) {
			return;
		}

		if (selectedFilter === 'States') {
			bufferStatesFilters.clear();
		} else {
			bufferServicesFilters.clear();
		}
	},
	true
);

// Apply filters
window.addEventListener(
	'click',
	(event) => {
		const applyButton = event.target.closest('.es-apply-filters-button-button');

		if (!applyButton) {
			return;
		}

		if (selectedFilter === 'States') {
			if (isFiltersLoaded) {
				statesFilter.clear();
			}

			bufferStatesFilters.forEach((v) => statesFilter.add(v));
		} else {
			if (isFiltersLoaded) {
				servicesFilter.clear();
			}
			bufferServicesFilters.forEach((v) => servicesFilter.add(v));
		}

		updateURL();
	},
	true
);

// Add & remove from buffer
window.addEventListener('click', (event) => {
	const filterButton = event.target.closest(
		'[class*="filter-dropdown__ContentBody-sc"] .es-filter-button-button'
	);

	if (!filterButton) {
		return;
	}

	const filterText = filterButton.querySelector('span').textContent.trim();

	if (selectedFilter === 'States') {
		if (bufferStatesFilters.has(filterText)) {
			bufferStatesFilters.delete(filterText);
		} else {
			bufferStatesFilters.add(filterText);
		}
	} else {
		if (bufferServicesFilters.has(filterText)) {
			bufferServicesFilters.delete(filterText);
		} else {
			bufferServicesFilters.add(filterText);
		}
	}
});

Please check your website and let me know if you like the result :slightly_smiling_face:

We also agree that it would be great to have this as a built-in option and I’ve moved this idea to the Wishlist. If more users support this request, it might be considered in the future.

2 Likes

This is great. Is there a way to have it work when on mobile still? on mobile the filters are not present and thus the links are not filtering the list if a user is on their phone

2 Likes

Hi there, @Info_at_BEST :waving_hand:

Thank you so much for flagging this up!

The filters don’t show up on mobile becuase the Search bar is disabled. The display of the filters shouldn’t be controlled with a Search bar toggle and our devs are currently investigating this bug. I’ll keep you updated :slightly_smiling_face:

As a temporary workaround, you can enable the Search bar and the filter will show up on mobile:

1 Like

The issue is - the search bar does not just search the locations configured but functions like a google search causing customers to find locations on our location page that are now our locations. So it gets confusing. I will probably have to await the bug fix! Thank you! (PS - you guys are awesome!)

2 Likes

Thank you so much for the feedback! We’ll keep you updated :blush:

We’ve applied a temporary fix to your widget and everything should be working fine now. Please check it out :slightly_smiling_face:

Once the global fix is released, I’ll update you here!