![]()
A Global Search feature across multiple Dataverse entities in a Power Pages portal offers a powerful and seamless way for users to find information, regardless of which table or module it belongs to — e.g., searching across Knowledge Articles, Products, Events, FAQs, or Cases in one unified experience.
Step-by-Step Guide to Building Global Search Across Multiple Entities
Step 1: Decide on Entities to Include
Choose which Dataverse tables (entities) should be part of the global search. Common examples:
knowledgearticleproductincident(Cases)custom_eventfaq_custom
For each entity, determine the searchable fields (like title, description, keywords, etc.).
Step 2: Enable Table Permissions
Set up Table Permissions for each of the selected entities:
- Go to Portal Management App
- Navigate to Table Permissions
- For each table:
- Table Name: Select the entity
- Permission Type:
Read - Access Type:
GlobalorContact(based on if records are public or user-specific)
- Associate permissions with the correct Web Role (e.g., Authenticated Users or Anonymous Users)
- Save and clear the portal cache
Step 3: Create a Unified HTML Search UI
<input type="text" id="globalSearchInput" placeholder="Search across the portal..." />
<div id="globalSearchResults"></div>
Step 4: Create Server-Side Liquid to Perform Searches
You’ll use multiple fetchxml blocks in Liquid to search across each entity.
{% assign query = request.params['search'] | escape %}
{% assign userId = user.id %}
{% fetchxml articleResults %}
<fetch top="5">
<entity name="knowledgearticle">
<attribute name="title" />
<filter>
<condition attribute="title" operator="like" value="%{{ query }}%" />
</filter>
</entity>
</fetch>
{% endfetchxml %}
{% fetchxml productResults %}
<fetch top="5">
<entity name="product">
<attribute name="name" />
<filter>
<condition attribute="name" operator="like" value="%{{ query }}%" />
</filter>
</entity>
</fetch>
{% endfetchxml %}
Step 5: Render Results in a Unified Format
<h3>Knowledge Articles</h3>
<ul>
{% for item in articleResults.results.entities %}
<li>{{ item.title }}</li>
{% else %}
<li>No articles found.</li>
{% endfor %}
</ul>
<h3>Products</h3>
<ul>
{% for item in productResults.results.entities %}
<li>{{ item.name }}</li>
{% else %}
<li>No products found.</li>
{% endfor %}
</ul>
Step 6: AJAX-Based Live Global Search (Optional Enhancement)
Use JavaScript to call a Web Page or Web Template asynchronously, and pass the user’s input.<script>
document.getElementById('globalSearchInput').addEventListener('keyup', function () {
const query = this.value;
if (query.length < 3) return;
fetch(`/global-search?search=${encodeURIComponent(query)}`)
.then(response => response.text())
.then(html => {
document.getElementById('globalSearchResults').innerHTML = html;
})
.catch(err => console.error('Search failed:', err));
});
</script>
Step 7: Optional – Paginate Results Per Entity
Use <paging> in FetchXML or a “Show More” link below each section to navigate to a dedicated page for that entity.
Step 8: Optional – Add Search Filters by Entity
Use dropdowns or tabs to let users refine the search per module:
<select id="entityFilter">
<option value="all">All</option>
<option value="article">Articles</option>
<option value="product">Products</option>
</select>
Modify the JavaScript to conditionally query per selection.
Step 9: Optimize Search Performance
- Limit results to top 5 or 10 per entity
- Use indexed fields in Dataverse
- Avoid over-querying by debouncing input (e.g., 300ms delay)
- Use caching where possible
Best Practices
- Avoid exposing too many fields from sensitive tables
- Use secured Web Roles to control visibility of each entity’s data
- Use clear section headers to differentiate results from various sources
- Implement logging or telemetry to measure search trends
Use Cases
- Public portal with knowledge articles and product details
- Internal portal with employee FAQs, HR documents, and IT support
- Customer portal combining orders, invoices, and FAQs
