Well no. You can’t create a “page” for search results. You have to use a template.
You select which template to use in https://app.hubspot.com/settings/[YOUR-PORTAL-ID-GOES-HERE]/website/pages/all-domains/system-pages
You’d build your search results template to mimmick your blog-listings template
You need to create a custom search results module to style the results.
The default hubspot search results module (@hubspot/search_results) uses this html:
<div class="hs-search-results">
<template class="hs-search-results__template">
<li>
{% if module.display_featured_images %}
<div class="hs-search-results__featured-image">
<img src="">
</div>
{% endif %}
<a href="#" class="hs-search-results__title">Content Title</a>
<p class="hs-search-results__description">Description</p>
</li>
</template>
<ul id="hsresults" class="hs-search-results__listing"></ul>
<div class="hs-search-results__pagination" data-search-path="{{ site_settings.content_search_results_page_path }}">
<a href="" class="hs-search-results__prev-page"></a>
<a href="" class="hs-search-results__next-page"></a>
</div>
</div>
and this javascript
var hsResultsPage = function(_resultsClass) {
function buildResultsPage(_instance) {
var resultTemplate = _instance.querySelector(
'.hs-search-results__template'
);
var resultsSection = _instance.querySelector('.hs-search-results__listing');
var searchPath = _instance
.querySelector('.hs-search-results__pagination')
.getAttribute('data-search-path');
var prevLink = _instance.querySelector('.hs-search-results__prev-page');
var nextLink = _instance.querySelector('.hs-search-results__next-page');
var searchParams = new URLSearchParams(window.location.search.slice(1));
/**
* v1 of the search input module uses the `q` param for the search query.
* This check is a fallback for a mixed v0 of search results and v1 of search input.
*/
if (searchParams.has('q')) {
searchParams.set('term', searchParams.get('q'));
searchParams.delete('q');
}
function getTerm() {
return searchParams.get('term') || '';
}
function getOffset() {
return parseInt(searchParams.get('offset')) || 0;
}
function getLimit() {
return parseInt(searchParams.get('limit'));
}
function addResult(title, url, description, featuredImage) {
var newResult = document.importNode(resultTemplate.content, true);
function isFeaturedImageEnabled() {
if (
newResult.querySelector('.hs-search-results__featured-image > img')
) {
return true;
}
}
newResult.querySelector('.hs-search-results__title').innerHTML = title;
newResult.querySelector('.hs-search-results__title').href = url;
newResult.querySelector(
'.hs-search-results__description'
).innerHTML = description;
if (typeof featuredImage !== 'undefined' && isFeaturedImageEnabled()) {
newResult.querySelector(
'.hs-search-results__featured-image > img'
).src=featuredImage;
}
resultsSection.appendChild(newResult);
}
function fillResults(results) {
results.results.forEach(function(result, i) {
addResult(
result.title,
result.url,
result.description,
result.featuredImageUrl
);
});
}
function emptyPagination() {
prevLink.innerHTML = '';
nextLink.innerHTML = '';
}
function emptyResults(searchedTerm) {
resultsSection.innerHTML =
'<div class="hs-search__no-results"><p>Sorry. There are no results for "' +
searchedTerm +
'"</p>' +
'<p>Try rewording your query, or browse through our site.</p></div>';
}
function setSearchBarDefault(searchedTerm) {
var searchBars = document.querySelectorAll('.hs-search-field__input');
Array.prototype.forEach.call(searchBars, function(el) {
el.value = searchedTerm;
});
}
function httpRequest(term, offset) {
var SEARCH_URL = '/_hcms/search?';
var requestUrl = SEARCH_URL + searchParams + '&analytics=true';
var request = new XMLHttpRequest();
request.open('GET', requestUrl, true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
var data = JSON.parse(request.responseText);
setSearchBarDefault(data.searchTerm);
if (data.total > 0) {
fillResults(data);
paginate(data);
} else {
emptyResults(data.searchTerm);
emptyPagination();
}
} else {
console.error('Server reached, error retrieving results.');
}
};
request.onerror = function() {
console.error('Could not reach the server.');
};
request.send();
}
function paginate(results) {
var updatedLimit = getLimit() || results.limit;
function hasPreviousPage() {
return results.page > 0;
}
function hasNextPage() {
return results.offset <= results.total - updatedLimit;
}
if (hasPreviousPage()) {
var prevParams = new URLSearchParams(searchParams.toString());
prevParams.set(
'offset',
results.page * updatedLimit - parseInt(updatedLimit)
);
prevLink.href = '/' + searchPath + '?' + prevParams;
prevLink.innerHTML = '< Previous page';
} else {
prevLink.parentNode.removeChild(prevLink);
}
if (hasNextPage()) {
var nextParams = new URLSearchParams(searchParams.toString());
nextParams.set(
'offset',
results.page * updatedLimit + parseInt(updatedLimit)
);
nextLink.href = '/' + searchPath + '?' + nextParams;
nextLink.innerHTML = 'Next page >';
} else {
nextLink.parentNode.removeChild(nextLink);
}
}
var getResults = (function() {
if (getTerm()) {
httpRequest(getTerm(), getOffset());
} else {
emptyPagination();
}
})();
}
(function() {
var searchResults = document.querySelectorAll(_resultsClass);
Array.prototype.forEach.call(searchResults, function(el) {
buildResultsPage(el);
});
})();
};
if (
document.attachEvent
? document.readyState === 'complete'
: document.readyState !== 'loading'
) {
var resultsPages = hsResultsPage('div.hs-search-results');
} else {
document.addEventListener('DOMContentLoaded', function() {
var resultsPages = hsResultsPage('div.hs-search-results');
});
}
To return the search results.
You would need to clone that module and edit the html and javascript to match your blog layout.
It looks like your blog is using a blog.css file you’d likely want to add that to your search results page template also, with something like:
{% set template_css = "../../css/templates/blog.css" %}
Barry Grennan
Freelance HubSpot CMS Developer
Website | Contact | LinkedIn