HH Components Reference Guide
Hubhus hh- components are powerful tools for dynamically fetching and displaying data in your campaigns. This comprehensive reference guide provides copy-paste examples organized by use case, making it easy to implement dynamic features in your emails, forms, and pages.
Build component code visually with our web-based generator tool
Note: This is a community tool, not an official Hubhus feature. Contact support@hubhus.com for assistance.
On this page
- HH Components Reference Guide
What are HH components?
HH components are custom HTML elements that start with hh- and fetch or process data from your Hubhus campaign. They work like placeholders but provide much more powerful functionality:
- Data fetching – Pull calendar events, leads, services, resources, and more
- Data processing – Count items, format dates, filter results
- Conditional logic – Show/hide content based on data availability
- Iteration – Loop through data collections
- Integrations – Embed maps, external services, and APIs
How to use this guide
Each section below contains ready-to-use code examples. Simply copy the code, replace the placeholders (marked with YOUR_VALUE_HERE), and paste into your template.
Calendar Events
Fetch and display calendar events with full control over filtering, sorting, and included relations.
Fetch all upcoming events
<hh-for each="event" in='<hh-data.calendar-events
where="start>@now"
sort="start"
limit="50" />'>
<div>
<strong>{event.title}</strong><br>
Date: {event.start}<br>
Location: {event.location}
</div>
</hh-for>Parameters explained:
where="start>@now"– Only events starting after current date/timesort="start"– Sort by start date (ascending)limit="50"– Maximum 50 results
Fetch events in a specific date range
<hh-for each="event" in='<hh-data.calendar-events
filter="start > @str2datetime[2025-12-01 00:00]"
filter="start < @str2datetime[2025-12-31 23:59]"
sort="start"
limit="500" />'>
Event: {event.title} on {event.start}
</hh-for>Use case: Display all events in December 2025.
Important
For date ranges, use filter with @str2datetime instead of where to avoid date parsing issues.
Fetch events with resource information
<hh-for each="event" in='<hh-data.calendar-events
include="calendar_resources.user"
where="start>@now"
sort="start"
limit="50" />'>
<div>
<strong>{event.title}</strong><br>
Assigned to: <hh-for each='res' in='event.calendar_resources' glue=", ">{res.user.name}</hh-for>
</div>
</hh-for>What this does: Shows each event with the names of all assigned resources, separated by commas.
Fetch events with service information
<hh-for each="event" in='<hh-data.calendar-events
include="calendar_services"
where="start>@now"
sort="start"
limit="50" />'>
<div>
<strong>{event.title}</strong><br>
Service: <hh-for each='srv' in='event.calendar_services' glue=", ">{srv.name}</hh-for>
</div>
</hh-for>Count total events
You have <hh-data.count><hh-data.calendar-events where="start>@now" /></hh-data.count> upcoming events.
Result: "You have 15 upcoming events."
Leads
Fetch and display lead information from your campaigns.
Fetch recent leads
<hh-for each="lead" in='<hh-data.leads
sort="created_at"
limit="10" />'>
<div>
<strong>{lead.name}</strong><br>
Email: {lead.email}<br>
Phone: {lead.phone}<br>
Created: {lead.created}
</div>
</hh-for>Note: Use sort="created_at" to sort by creation date (ascending). For descending (newest first), check if your system supports sort="-created_at" or use a different field.
Filter leads by status
<hh-for each="lead" in='<hh-data.leads
filter-status="slug = moede-booket"
sort="created_at"
limit="50" />'>
{lead.name} - {lead.email}
</hh-for>Replace "moede-booket" with your actual status slug. Important: Note the space around the equals sign: "slug = value" not "slug=value".
Filter leads by custom field
<hh-for each="lead" in='<hh-data.leads
filter-field_value="zipcode LIKE 20*"
sort="created_at"
limit="50" />'>
{lead.name} - {lead.email}
</hh-for>Use case: Filter by custom field values using filter-field_value instead of where.
Count leads
Total leads: <hh-data.count><hh-data.leads /></hh-data.count> Active leads: <hh-data.count><hh-data.leads filter-status="slug = active" /></hh-data.count>
Booking Availability
Check available booking times and control booking form behavior.
Check if booking slots are available
@if(<hh-data.count><hh-booking.available-dates
booking-form="YOUR_BOOKING_FORM_ID"
full-address="%lead_full_address%"
latest-date="+14days" /></hh-data.count> > 0){
Booking slots are available!
}@else{
No slots available in the next 14 days.
}@endifParameters:
booking-form="YOUR_BOOKING_FORM_ID"– Replace with your booking form IDfull-address="%lead_full_address%"– The address to check availability forlatest-date="+14days"– Check availability up to 14 days ahead
Get optimal booking time slots
<hh-for each="slot" in='<hh-booking.optimal-datetime-slots
booking-form="YOUR_BOOKING_FORM_ID"
full-address="%lead_full_address%"
earliest-date="@now"
latest-date="+30days"
limit="5" />'>
Available: {slot.datetime} ({slot.score}% optimal)
</hh-for>Use case: Show the top 5 most optimal booking times based on resource availability and efficiency.
Use in automation conditions
@if(<hh-data.count><hh-booking.available-dates
latest-date="+10days"
booking-form="YOUR_BOOKING_FORM_ID"
full-address="%lead_full_address%" /></hh-data.count> > 1){1}@else{0}@endifResult: Returns 1 (true) if more than one slot is available, otherwise 0 (false). Perfect for automation triggers.
Calendar Resources
Fetch resource information, groups, and tags for dynamic resource selection.
List all resource groups
<hh-data.calendar-resource-groups pluck="name,id" />
Output example:
{
"176": "Installation Team",
"177": "Installation Team - North",
"178": "Installation Team - South",
"179": "Service Team - East"
}Use case: Programmatically fetch all resource tag names and IDs for dynamic resource selection in booking forms.
List all calendar services
<hh-data.calendar-services pluck="name,id" limit="200" />
Result: JSON object with all service names and IDs.
Date Formatting
Format dates for display or calculations.
Format a date
<hh-date.format input="%event_start_datetime_db%" output="d/m/Y" />
Result: "15/12/2025"
Calculate a date (add/subtract days)
<hh-date.format input="%event_start_datetime_db% -1day" output="Y-m-d" />
Result: Date one day before the event start (e.g., "2025-12-14")
Common calculations:
+7days– Add 7 days-3days– Subtract 3 days+2weeks– Add 2 weeks-1month– Subtract 1 month
Important
Always use the _db variant of date placeholders (e.g., %event_start_datetime_db%) when doing date calculations. Also ensure there is a space before the calculation: %date% -1day not %date%-1day.
Use in hidden form inputs
<input name='latest_date' value='<hh-date.format input="%event_start_datetime_db% -1day" output="Y-m-d" />' type='hidden' />
Use case: Limit booking form date picker to show only dates before the current event.
Data Fields
Read and display custom data field values (JSON structured data).
Read a data field value
<hh-for each='item' in='<hh-data-fields.value slug="YOUR_DATA_FIELD_SLUG" />'>
<div>
Name: {item.name}<br>
Value: {item.value}<br>
Quantity: {item.quantity}
</div>
</hh-for>Replace YOUR_DATA_FIELD_SLUG with your data field's slug (API name).
Use case: Display line items from an invoice, checklist items, product selections, or any structured JSON data stored in a data field.
Maps Integration
Embed Google Maps features directly into your templates.
Embed Google Street View
<div style='max-width:100%; min-height: 400px;'>
<hh-gmap.street-view
location="%lead_full_address%"
style='min-height: 500px;' />
</div>Use case: Show property street view in lead profile pages, booking confirmations, or inspection reports.
Counting and Data Validation
Count results from any data source for conditional logic.
General counting syntax
<hh-data.count> <hh-data.COMPONENT_NAME [parameters] /> </hh-data.count>
Wraps any hh-data.* component to return the count instead of the data.
Count examples
<!-- Count upcoming events --> <hh-data.count><hh-data.calendar-events where="start>@now" /></hh-data.count> <!-- Count available booking slots --> <hh-data.count><hh-booking.available-dates booking-form="123" full-address="%lead_full_address%" /></hh-data.count> <!-- Count leads with specific status --> <hh-data.count><hh-data.leads filter-status="slug = qualified" /></hh-data.count>
Counting Microsoft Calendar Events
Count Microsoft 365 calendar events with advanced filtering options for resources, time ranges, and combinations.
Filter by specific resource (by ID):
<hh-data.microsoft-events.count filter-calendar_resources="id = 1790" />
Filter by resource email:
<hh-data.microsoft-events.count filter-calendar_resources="email = john@company.com" />
Time interval - This week:
<hh-data.microsoft-events.count filter="start > @str2datetime[monday this week]" filter="start < @str2datetime[sunday this week]" />
Time interval - Next week:
<hh-data.microsoft-events.count filter="start > @str2datetime[monday next week]" filter="start < @str2datetime[sunday next week 23:59]" />
Combined filters - Specific resource this week:
<hh-data.microsoft-events.count filter-calendar_resources="id = 1790" filter="start > @str2datetime[monday this week]" filter="start < @str2datetime[sunday this week 23:59]" />
Advanced - Count by resource tag/group:
<hh-calculator precision="0">0<hh-for each="resource" in='<hh-data.calendar-resource-groups.first filter="id=140" include="calendar_resources" get="calendar_resources" />'>+<hh-data.microsoft-events.count filter="start > @str2datetime[monday this week]" filter="start < @str2datetime[sunday this week 23:59]" filter-calendar_resources="id = {resource.id}" /></hh-for></hh-calculator>Finding resource tag IDs
To find all resource tag IDs for use in filters, use:<hh-data.calendar-resource-groups output="html-table-style-one" />
Common Parameters
These parameters work across multiple components:
Filtering (where vs filter)
For simple properties: Use where
where="field_name=value" where="field_name>value" where="field_name<value" where="field_name!=value"
For date ranges: Use filter with @str2datetime
filter="start > @str2datetime[today]" filter="start < @str2datetime[tomorrow]"
For custom field filtering (leads only):
filter-field_value="zipcode LIKE 20*" filter-status="slug = won"
Pro tip
Use filter instead of where for date ranges to avoid parsing errors. You can use multiple filter or where attributes together.
Sorting (sort)
sort="field_name" <!-- Ascending (A-Z, oldest-newest) --> sort="-field_name" <!-- Descending (Z-A, newest-oldest) -->
Examples:
sort="start"– Sort calendar events by start date (earliest first)sort="-start"– Sort calendar events by start date (newest first)sort="created_at"– Sort leads by creation date (oldest first)sort="name"– Sort alphabetically by name
Important
For leads, use sort="created_at" (not "created"). For calendar events, use sort="start". Different data types may use different field names.
Limiting results (limit)
limit="10" <!-- Return maximum 10 results -->
Including related data (include)
include="calendar_resources.user" <!-- Include resource with user info --> include="calendar_services" <!-- Include service info --> include="calendar_resources,calendar_services" <!-- Multiple includes -->
Plucking specific fields (pluck)
pluck="name" <!-- Return only name field --> pluck="name,id" <!-- Return name and id fields -->
Use case: Reduce data size and output only needed fields.
Loop Syntax (hh-for)
Iterate through data collections returned by components.
Basic loop structure
<hh-for each="ITEM_NAME" in='<hh-data.COMPONENT [params] />'>
{ITEM_NAME.field_name}
</hh-for>Components:
each="ITEM_NAME"– Variable name for each item (choose any name)in='...'– The component that returns data{ITEM_NAME.field}– Access item properties inside the loop
Loop with separator (glue)
<hh-for each='res' in='event.calendar_resources' glue=", ">
{res.user.name}
</hh-for>Result: "John Smith, Sarah Johnson, Mike Davis"
Common separators:
glue=", "– Comma and spaceglue=" | "– Pipe separatorglue="<br>"– Line breaks
Nested loops
<hh-for each="event" in='<hh-data.calendar-events include="calendar_resources.user" limit="10" />'>
<div>
<strong>{event.title}</strong><br>
Resources:
<ul>
<hh-for each='res' in='event.calendar_resources'>
<li>{res.user.name} ({res.user.email})</li>
</hh-for>
</ul>
</div>
</hh-for>Practical Real-World Examples
Complete examples ready to use in production.
Email notification with availability check
<p>Hi %lead_firstname%,</p>
@if(<hh-data.count><hh-booking.available-dates
booking-form="YOUR_FORM_ID"
full-address="%lead_full_address%"
latest-date="+7days" /></hh-data.count> > 0){
<p>Good news! We have available times this week:</p>
<p><a href="@bookingFormUrlLead[YOUR_FORM_NAME]">Click here to book</a></p>
}@else{
<p>Unfortunately, we're fully booked this week. We'll contact you when new times become available.</p>
}@endifLead dashboard with counts
<div style="background: #f3f2f1; padding: 20px; border-radius: 8px;">
<h2>Campaign Dashboard</h2>
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
<div style="background: white; padding: 15px; border-radius: 4px;">
<h3><hh-data.count><hh-data.leads /></hh-data.count></h3>
<p>Total Leads</p>
</div>
<div style="background: white; padding: 15px; border-radius: 4px;">
<h3><hh-data.count><hh-data.calendar-events where="start>@now" /></hh-data.count></h3>
<p>Upcoming Events</p>
</div>
<div style="background: white; padding: 15px; border-radius: 4px;">
<h3><hh-data.count><hh-data.leads filter-status="slug = interested" /></hh-data.count></h3>
<p>Interested Leads</p>
</div>
</div>
</div>Booking form with conditional availability
<div class="form-group">
<h3>Book Your Appointment</h3>
@if(%event_datetime%){
@if(1 > <hh-data.count><hh-booking.available-dates
latest-date="+21days"
booking-form="YOUR_FORM_ID"
full-address="%lead_full_address%" /></hh-data.count>){
<p>You have a booking on <b>%event_datetime%</b></p>
<p>You already have the earliest available time. We look forward to seeing you!</p>
}@else{
<p>You have a booking on <b>%event_datetime%</b></p>
<p>We can offer you an earlier time if you'd like. Select a date and time below.</p>
}@endif
}@else{
<p>Select your preferred date and time:</p>
}@endif
</div>Component Shortcuts
Most data components have shortcut variants for common operations:
Direct count variants
Instead of wrapping with <hh-data.count>, use direct count variants:
<!-- Standard way --> <hh-data.count><hh-data.calendar-events where="start>@now" /></hh-data.count> <!-- Shortcut way --> <hh-data.calendar-events.count where="start>@now" />
Available shortcuts:
hh-data.calendar-events.counthh-data.leads.counthh-data.calendar-services.counthh-data.calendar-resource-groups.count
Get first item variants
Get the first item from a collection without looping:
<!-- Get first upcoming event -->
@with(event = <hh-data.calendar-events.first where="start>@now" />){
Next event: {event.title} on {event.start}
}@endwith
<!-- Get first lead -->
@with(lead = <hh-data.leads.first sort="created_at" />){
Latest lead: {lead.name}
}@endwithAvailable shortcuts:
hh-data.calendar-events.firsthh-data.leads.firsthh-data.calendar-services.firsthh-data.calendar-resource-groups.first
Troubleshooting
Component not rendering
If a component doesn't display data:
- Check that all required parameters are provided
- Verify parameter values are correct (IDs, slugs, field names)
- Ensure placeholders inside parameters are valid (e.g.,
%lead_full_address%) - Check for typos in component names (
hh-data.calendar-events, nothh-calendar-events) - Test with simple examples first, then add complexity
Date range filtering errors
Common mistake: Using where for date ranges
Wrong
where="start>2025-12-01" where="start<2025-12-31"
Correct
filter="start > @str2datetime[2025-12-01]" filter="start < @str2datetime[2025-12-31]"
Date calculation errors
Common mistakes:
Wrong
input="%date%-1day"- Missing space before calculationinput="%event_start_datetime% -1day"- Should use_dbvariant
Correct
input="%event_start_datetime_db% -1day"
Custom field filtering errors
Common mistake: Using where for custom fields
Wrong
where="zipcode=2000"
Correct
filter-field_value="zipcode = 2000"
Empty results or zero count
If components return no data:
- Verify data exists that matches your filter conditions
- Use
filterwith@str2datetimefor date ranges - Remove filters temporarily to see all results
- Check that the lead/event has the required related data
Syntax errors
Common syntax mistakes:
- Missing closing tags: Ensure
</hh-for>and</hh-data.count>are present - Incorrect quotes: Use single quotes inside
in='...'attributes - Unescaped special characters: Use
<instead of<in HTML context - Missing self-closing slash: Components must end with
/>
Best Practices
Performance
- Always use
limitparameter to restrict result counts - Use
wherefilters to reduce data volume - Only
includerelated data when needed - Use
pluckto return only required fields
Maintainability
- Add comments to complex logic:
<!-- Check availability for next 14 days --> - Use descriptive variable names in loops:
each="event"noteach="e" - Break complex nested structures into separate components
- Document parameter values for future reference
Testing
- Test with multiple leads to ensure data variations are handled
- Test with empty data sets to verify fallback logic
- Test in different contexts (emails, forms, pages)
- Preview emails before sending to production
Summary
HH components provide powerful data fetching and processing capabilities for Hubhus campaigns. Use hh-data.calendar-events to fetch calendar events with filtering, sorting, and related data (resources, services). Use hh-booking.available-dates and hh-booking.optimal-datetime-slots to check booking availability and display optimal times. Use hh-data.count to wrap any component and return the count instead of data—perfect for conditional logic in automations. Use hh-date.format to format and calculate dates with operations like +7days or -1month. Use hh-data-fields.value to read structured JSON data from custom data fields. Use hh-gmap.street-view to embed Google Street View for addresses. Use hh-for to loop through data collections with optional separators using glue. Common parameters include where for filtering, sort for ordering (use -field for descending), limit for restricting results, include for loading related data, and pluck for selecting specific fields. Always use limits to maintain performance, add comments for complex logic, and test with various data scenarios. Components can be nested, combined with conditional logic, and used across emails, forms, pages, and automation templates.
Common searches
hh components • dynamic data • fetch calendar events • check booking availability • loop through data • data fields • count results • date formatting • calendar resources • placeholders advanced
Also known as
hubhus components • dynamic components • data components • template components • hh tags • custom placeholders • dynamic content • API components
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article