How do I generate SEO URL's using Instantsearch

430 Views Asked by At

I'm using Algolia's Instantsearch.js with Typesense adapter, which works well for my search page, but if I go to the search page with a query or refinement in the URL, it doesn't filter. For example, if I do https://example.com/buy-list/buying/Sports (sports being the category), it doesn't automatically filter.

Here is the relevant snippet. I've narrowed it down to somewhere in the router because if I set it router: true, it works, it's just not pretty URL's.

const search = instantsearch({
            searchClient,
            indexName: INSTANT_SEARCH_INDEX_NAME,
            routing: {
                router: instantSearchRouter({
                    windowTitle({category, query}) {
                        const queryTitle = query ? `Results for "${query}"` : 'Buy List | DA Card World';

                        if (category) {
                            return `${category} – ${queryTitle}`;
                        }

                        return queryTitle;
                    },
                    createURL({qsModule, routeState, location}) {
                        const urlParts = location.href.match(/^(.*?)\/buying\/buy-list/);
                        const baseUrl = `${urlParts ? urlParts[1] : ''}/`;

                        const categoryPath = routeState.category
                            ? `${getCategorySlug(routeState.category)}/`
                            : '';

                        const queryParameters = {};

                        if (routeState.query) {
                            queryParameters.query = encodeURIComponent(routeState.query);
                        }

                        if (routeState.page !== 1) {
                            queryParameters.page = routeState.page;
                        }

                        if (routeState.types) {
                            queryParameters.types = routeState.types.map(encodeURIComponent);
                        }

                        if (routeState.years) {
                            queryParameters.years = routeState.years.map(encodeURIComponent);
                        }

                        if (routeState.series) {
                            queryParameters.series = routeState.series.map(encodeURIComponent);
                        }

                        const queryString = qsModule.stringify(queryParameters, {
                            addQueryPrefix: true,
                            arrayFormat: 'repeat'
                        });

                        return `${baseUrl}buying/buy-list/${categoryPath}${queryString}`;
                    },
                    parseURL({qsModule, location}) {
                        const pathnameMatches = location.pathname.match(/\/buying\/buy-list\/(.*?)\/?$/);
                        const category = getCategoryName(
                            (pathnameMatches && pathnameMatches[1]) || ''
                        );

                        const {query = '', page, types = [], years = [], series = []} = qsModule.parse(
                            location.search.slice(1)
                        );

                        // `qs` does not return an array when there's a single value.
                        const allTypes = Array.isArray(types) ? types : [types].filter(Boolean);
                        const allYears = Array.isArray(years) ? years : [years].filter(Boolean);
                        const allSeries = Array.isArray(series) ? series : [series].filter(Boolean);

                        return {
                            query: decodeURIComponent(query),
                            page,
                            types: allTypes.map(decodeURIComponent),
                            years: allYears.map(decodeURIComponent),
                            series: allSeries.map(decodeURIComponent),
                            category
                        };
                    }
                }),
                stateMapping: {
                    stateToRoute(uiState) {
                        const indexUiState = uiState[INSTANT_SEARCH_INDEX_NAME] || {};

                        return {
                            query: indexUiState.query,
                            page: indexUiState.page,
                            types: indexUiState.refinementList && indexUiState.refinementList.package,
                            years: indexUiState.refinementList && indexUiState.refinementList.year,
                            series: indexUiState.refinementList && indexUiState.refinementList.series,
                            category: indexUiState.hierarchicalMenu && indexUiState.hierarchicalMenu[INSTANT_SEARCH_HIERARCHICAL_ATTRIBUTE]
                                && indexUiState.hierarchicalMenu[INSTANT_SEARCH_HIERARCHICAL_ATTRIBUTE].join('>')
                        };
                    },
                    routeToState(routeState) {
                        return {
                            instant_search: {
                                query: routeState.query,
                                page: routeState.page,
                                hierarchicalMenu: {
                                    "category": routeState.category && routeState.category.split('>')
                                },
                                refinementList: {
                                    packages: routeState.types,
                                    years: routeState.years,
                                    series: routeState.series
                                }
                            }
                        };
                    }
                }
            },
            searchFunction: function (helper) {
                helper.search();

                const title = document.querySelector('title');
                const header = document.querySelector('#results_title');
                let titleText = 'Buy Lists';

                if (INSTANT_SEARCH_HIERARCHICAL_ATTRIBUTE in helper.state.hierarchicalFacetsRefinements) {
                    titleText = helper.state.hierarchicalFacetsRefinements[INSTANT_SEARCH_HIERARCHICAL_ATTRIBUTE] + ' Buy List';
                }

                title.text = titleText + ' | DA Card World';
                header.innerText = titleText;
            }
        });
0

There are 0 best solutions below