Custom site google search

Regular Contributor

Hi all, 

 

I was wondering how I can implement custom search in my HubSpot site. My templates are custom code and not using the drag-and-drop builder. 

 

I read this article and know how to make it using the google custom search engine - designers.hubspot.com/blog/how-to-custom-search-hubspot-cos-website 

 

But that option has ads and I want a clean version. The issue is that google is shutting down their paid version of custom search - https://cse.google.com/cse/

 

Is there an solution for this within Hubspot?

 

Thanks

11 Replies 11
Occasional Contributor

Hi, try using the Google's Site Search (which is actually their paid service for site search tools). https://cse.google.com/compare. Also, I could not find any information about Google shutting down their paid search service for websites. 

Reply
0 Upvotes
Regular Contributor

Hi, if you click on get started on that link it takes you to a page which details how it will be shut down. It gives the following message: 

 

site.png

Reply
0 Upvotes
Highlighted
Regular Contributor

The best solution so far that I have found is the repo here: 

https://github.com/growwithsms/HubSpot-COS-Site-Search

 

However this only searches the titles, I need a way to search the content

Reply
0 Upvotes
Esteemed Advisor

@A2mun,

 

That module was actually written by @stefen who is a regular on these boards. Maybe he could chime in with some modification help.

 

I actually just created a custom search for a resource page that checked the searched term against all of the blogs components (title, content, image, custom module content) and returned any matches on the listing page. This would work for a site wide search except that I cannot seam to find a token that contains the published pages.

- Jonathan Sumner
Regular Contributor

My website is not a blog, it is just a set of "website pages". How did you get this custom search against all components, using stefan's module?

 

Thanks

Reply
0 Upvotes
Esteemed Advisor

@A2mun,

 

No in my case I had the blogs contents loop to search through. 

 

I created a variable for the query:

{% set query = request.query_dict.q|lower %}

created a search bar to pass a query to the url:

<form id="tagForm">
            <div class="page_center large">
                <input id="keyword" type="search" value="{% if query is defined %} {{ query }} {% endif %} ">
                <button type="submit"></button>
            </div>
</form>

<script>

$(document).ready(function() {
     $('#tagForm').submit( function() {              
          goUrl = 'SiteURL/resources' + '?q=' + $('#keyword').val().toLowerCase();
          window.location = goUrl;
          return false;  // Prevent the default form behaviour
     });
});
</script>

and a custom for contents loop if a query is present in the url:

{% if query is defined %}

{% for content in contents %}
                            
    {% set title = content.widgets.resource_title.body.value|lower %}
    {% set type = content.widgets.resource_content_type.body.value|lower %}
    {% set summary = content.widgets.resource_content_type.body.value|lower %}
    {% set topic = in content.topic_list|map('name')|lower %}
                            
    {%if query in title or query in type or query in summary or query in topic %}
                                
        <div class="resource_item {{ content.widgets.resource_content_type.body.value|lower }}">
              <a class="resource_featured_image" href="{{ content.widgets.resource_link.body.value }}" style="background: url({{ content.widgets.resource_image.body.src }});"></a>
              <h2><a href="{{ content.widgets.resource_link.body.value }}">{{ content.widgets.resource_title.body.value }}</a></h2>
              <div class="sum_wrap">
                   {{ content.widgets.resource_summary.body.value }}
              </div>
              <a class="resource_read_more" href="{{ content.widgets.resource_link.body.value }}">{{ content.widgets.resource_button_text.body.value }}</a>
         </div>
                                
     {% endif %}
                            
{% endfor %}
                    
 {% endif %}

This was based off of a request to have the clients resource page searchable like Hubspots search page. It works pretty much the same.

 

This would work in your case to only you would need to redirect to a different page with the query and use an array like contents that gives you access to all of the pages on your site. I can't seam to find anything that allows this. without having access to all of the pages and their content to loop through this won't work. 

 

- Jonathan Sumner
Top Contributor

Thanks for your assistance could you explain in more detail where
{% set query = request.query_dict.q|lower %} should be placed.

 

Also I have added the last part of the code in the listing template underneath the existing code that builds out the page is this correct?

 

EXISTING CODE

<div class="blog-section portfolio">
<div class="blog-listing-wrapper cell-wrapper">
<div class="row same-height-parent isotope" style="display:flex; flex-wrap:wrap;">
{% for content in contents %}
<div class="span4 resource-listing-thumb original inspire-site {{ content.widgets.filter.body.value }} {{ content.widgets.resource_type.body.value }}">
<!--<a href="{{ content.absolute_url }}" class="inspire-block"> -->
<a href="{{ content.widgets.resource_link.body.value }}" class="inspire-block">
<div class="portfolio-image-wrapper">
<img class="portfolio-image" src="{{ content.widgets.thumbnail_image.body.src }}" alt="{{ content.widgets.listingimage.body.alt }}" />
<!--<span class="cta orange">See More</span> -->
</div>
<!--<span class="portfolio-title same-height"> {{ content.name}} </span> -->
<h4>{{content.name }}</h4
</a>
</div>
{% endfor %}

NEW CODE ADDED
{% if query is defined %}

{% for content in contents %}
{% set title = content.widgets.resource_title.body.value|lower %}
{% set type = content.widgets.resource_content_type.body.value|lower %}
{% set summary = content.widgets.resource_content_type.body.value|lower %}
{% set topic = in content.topic_list|map('name')|lower %}
{%if query in title or query in type or query in summary or query in topic %}
<div class="resource_item {{ content.widgets.resource_content_type.body.value|lower }}">
<a class="resource_featured_image" href="{{ content.widgets.resource_link.body.value }}" style="background: url({{ content.widgets.resource_image.body.src }});"></a>
<h2><a href="{{ content.widgets.resource_link.body.value }}">{{ content.widgets.resource_title.body.value }}</a></h2>
<div class="sum_wrap">
{{ content.widgets.resource_summary.body.value }}
</div>
<a class="resource_read_more" href="{{ content.widgets.resource_link.body.value }}">{{ content.widgets.resource_button_text.body.value }}</a>
</div>
{% endif %}
{% endfor %}
{% endif %}


</div>

 

 

So the code for the listing page is:

<div class="blog-section portfolio">
<div class="blog-listing-wrapper cell-wrapper">
<div class="row same-height-parent isotope" style="display:flex; flex-wrap:wrap;">
{% for content in contents %}
<div class="span4 resource-listing-thumb original inspire-site {{ content.widgets.filter.body.value }} {{ content.widgets.resource_type.body.value }}">
<!--<a href="{{ content.absolute_url }}" class="inspire-block"> -->
<a href="{{ content.widgets.resource_link.body.value }}" class="inspire-block">
<div class="portfolio-image-wrapper">
<img class="portfolio-image" src="{{ content.widgets.thumbnail_image.body.src }}" alt="{{ content.widgets.listingimage.body.alt }}" />
<!--<span class="cta orange">See More</span> -->
</div>
<!--<span class="portfolio-title same-height"> {{ content.name}} </span> -->
<h4>{{content.name }}</h4
</a>
</div>
{% endfor %}

{% if query is defined %}

{% for content in contents %}

{% set title = content.widgets.resource_title.body.value|lower %}
{% set type = content.widgets.resource_content_type.body.value|lower %}
{% set summary = content.widgets.resource_content_type.body.value|lower %}
{% set topic = in content.topic_list|map('name')|lower %}

{%if query in title or query in type or query in summary or query in topic %}

<div class="resource_item {{ content.widgets.resource_content_type.body.value|lower }}">
<a class="resource_featured_image" href="{{ content.widgets.resource_link.body.value }}" style="background: url({{ content.widgets.resource_image.body.src }});"></a>
<h2><a href="{{ content.widgets.resource_link.body.value }}">{{ content.widgets.resource_title.body.value }}</a></h2>
<div class="sum_wrap">
{{ content.widgets.resource_summary.body.value }}
</div>
<a class="resource_read_more" href="{{ content.widgets.resource_link.body.value }}">{{ content.widgets.resource_button_text.body.value }}</a>
</div>

{% endif %}

{% endfor %}

{% endif %}


</div>

<hr >
<div class="blog-pagination">
{% if contents.total_page_count > 0 %}
{% if widget.range == 10 %}
{% set base = 10 %}
{% set loop_ = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] %}
{% else %}
{% set base = 5 %}
{% set loop_ = ['1', '2', '3', '4', '5'] %}
{% endif %}

{% set current_pg_index = last_page_num + 1 %}
{% set range_start = ((1 - current_pg_index) % base) + current_pg_index %}

{# EXTRA: calculate start of previous range and end of next
{% set range_end = range_start + (base)-1 %}

{% set previous_range_start = ((6 - current_pg_index) % base) + current_pg_index - base %}
{% if previous_range_start < 1 %}
{% set previous_range_start = 1 %}
{% endif %}
#}
<ul>
<li class="first-posts-link {% if current_pg_index <= 1 %}hide{% endif %}"><a href="{{ blog_page_link(1) }}"><i class="fa fa-angle-double-left"></i></a></li>
<li class="previous-posts-link {% if !last_page_num %}hide{% endif %}"><a href="{{ blog_page_link(last_page_num) }}"><i class="fa fa-angle-left"></i></a></li>
<span class="pg">
{% set i = range_start %}
{% for pg in loop_ %} {# effectively, for i=1 to i=base #}
{% if i <= contents.total_page_count %}
<li{% if i == current_pg_index %} class="active"{% endif %}><a href="{{ blog_page_link(i) }}">{{ i }}</a></li>

{% set i = i + 1 %}
{% endif %}
{% endfor %}
</span>
<li class="next-posts-link {% if current_pg_index == contents.total_page_count %}hide{% endif %}"><a href="{{ blog_page_link(next_page_num) }}"><i class="fa fa-angle-right"></i></a></li>
<li class="last-posts-link {% if current_pg_index == contents.total_page_count %}hide{% endif %}"><a href="{{ blog_page_link(contents.total_page_count) }}"><i class="fa fa-angle-double-right"></i></a></li>
</ul>
{% endif %}
</div>
</div>
</div>

Reply
0 Upvotes
Esteemed Advisor

@Woodsy,

 

I placed the query variable and the search bar w/ javascript in a custom HubL module outside of the listing and post template code, in the main template. This is because they share a search bar so I needed it for both instead of one or the other. 

 

It doesn't matter where you place your query variable as long as you have it above the code that references it.

 

You are correct about the code that you placed in your listing template.

- Jonathan Sumner
New Contributor

Hey @Jsum

I've been trying to implement this into a blog search for the past few days and have been having a hard time. I can successfully search through titles and content, but topics are still evading me.

Here's what I have so far:


Form

 

<form action="url/search">
    <input class="margin-bottom-10" type="text" name="query" placeholder="Search the blog..." required>
    <button type="submit">Search</button
</form>


Listing Template

{% set searchQuery = request.query_dict['query'] %} 
{% set contents = blog_recent_posts('1490765805', 200) %}

{% if searchQuery is defined %}
            {% for content in contents %}
            
                {% set postTitle = content.name|lower %}
                {% set postContent = content.post_list_content %}
                {% set postTopic = content.topic_list|map('name')|lower %}
            
                {% if postTitle is string_containing searchQuery || postContent is string_containing searchQuery || postTopic is string_containing searchQuery %}
                       
                    <div class="post-item {% if content.topic_list %}{% for topic in content.topic_list -%}{{ topic.name|replace(" ", "-")|lower }}{% if not loop.last %} {% endif %}{% endfor %}{% endif %}">
                        <div class="post-body clearfix">
                            <!--post summary-->
                            {% if content.post_list_summary_featured_image %}
                            <div class="hs-featured-image-wrapper">
                                <a href="{{content.absolute_url}}" title="" class="hs-featured-image-link">
                                    <img src="{{ content.post_list_summary_featured_image }}" class="hs-featured-image">
                                </a>
                            </div>
                            {% endif %}
                            <h1><a href="{{content.absolute_url}}">{{ content.name }}</a></h1>
                                {{ content.post_list_content|safe|truncatehtml(500, '...') }}
                        </div>
                        <div class="post-footer">                            
                            <span class="post-date">{{ content.publish_date_localized }}</span>
                            {% if content.topic_list %}
                            <span id="hubspot-topic_data"> in:
                                {% for topic in content.topic_list %}
                                <a class="topic-link" href="{{ group.absolute_url }}/topic/{{ topic.slug }}">{{ topic.name }}</a>{% if not loop.last %},{% endif %}
                                {% endfor %}
                            </span>
                            {% endif %}
                        </div>
                    </div>
                       
                {% endif %}
                    
            {% endfor %}
            
            {% else %}
.........

Any help you can throw may way would be much appreciated!

 

Reply
0 Upvotes
Esteemed Advisor

@chubbaluv,

 

I would imagine that the "is string_containing" part is the issue. I might be wrong but I am pretty sure that the topics are delivered as a dict containing the slug and the topic name. I haven't had this issue before. I wrote a blog post about this method: http://www.khaoticdigital.com/blog/simple-hubspot-blog-search-function

 

% if query in title or query in post or query in topics %}

hasn't let me down yet, though I can't honestly say I remember whether or not I actually tested topics. I am pretty sure I did. The same search is implemented on my blog there.

- Jonathan Sumner
Reply
0 Upvotes
Occasional Contributor

Hi @A2mun,

 

Swiftype Site Search is a good alternative to Google Custom Search. It's easy to set up and comes with a dashboard where you can customize your search experience and view analytics. A few cool features:

- custom result ranking

- faceted search

- autocomplete dropdown

 

Swiftype's API is extensively documented and you can customize the search UI to match your templates. You can index any amount of content with Swiftype and new content is indexed automatically. 

Reply
0 Upvotes