Advanced Features
Nimbu provides advanced features for search, authentication, analytics, payments, and security to build sophisticated web applications.
Search
{% search %}
Built-in site search with filtering:
liquid
{% search params.q, in: 'products,pages,articles' %}
{% if search.results.size > 0 %}
<div class="search-results">
<h2>Found {{ search.results.size }} results for "{{ params.q }}"</h2>
{% for result in search.results %}
<div class="result">
<h3><a href="{{ result.url }}">{{ result.title }}</a></h3>
<p>{{ result.excerpt | highlight: params.q }}</p>
<span class="type">{{ result.type }}</span>
</div>
{% endfor %}
</div>
{% else %}
<p>No results found for "{{ params.q }}"</p>
{% endif %}
{% endsearch %}Search Parameters:
in- Content types to search: products, pages, articles, channelslimit- Maximum results (default: 50)locale- Search specific locale
Search Result Properties:
result.title- Result titleresult.url- Result URLresult.excerpt- Text excerptresult.type- Content typeresult.score- Relevance score
OAuth Authentication
{% login_with %}
Social login integration:
liquid
{% login_with 'google', redirect_to: '/account' %}
<!-- Generates Google OAuth login button -->
{% login_with 'facebook', class: 'btn btn-primary' %}
{% login_with 'twitter', text: 'Sign in with Twitter' %}Supported Providers:
google- Google OAuthfacebook- Facebook Logintwitter- Twitter OAuthgithub- GitHub OAuthlinkedin- LinkedIn OAuth
{% unlink_from %}
Remove OAuth connection:
liquid
{% if customer.google_connected %}
{% unlink_from 'google', text: 'Disconnect Google' %}
{% endif %}OAuth2 Consent Flow
liquid
{% oauth2_consent_form client_id: 'your_client_id' %}
<!-- Generates OAuth2 authorization form -->Analytics Integration
Google Analytics
liquid
<!-- In layout head -->
{{ 'UA-XXXXX-Y' | google_analytics }}
<!-- Or with Google Analytics 4 -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>Google Tag Manager
liquid
{{ 'GTM-XXXXX' | gtm }}Custom Event Tracking
liquid
<button
onclick="gtag('event', 'add_to_cart', {
'event_category': 'ecommerce',
'event_label': '{{ product.name }}',
'value': {{ product.price }}
})">
Add to Cart
</button>Payment Integration
Stripe Checkout
liquid
{{ order | payment_form, provider: 'stripe' }}Custom Stripe Integration:
liquid
<form id="payment-form">
<div id="card-element"></div>
<button type="submit">Pay {{ cart.total | money_with_currency }}</button>
</form>
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripe = Stripe('{{ site.stripe_public_key }}');
const elements = stripe.elements();
const card = elements.create('card');
card.mount('#card-element');
const form = document.getElementById('payment-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const {token} = await stripe.createToken(card);
// Submit token to your payment endpoint
fetch('/checkout/process', {
method: 'POST',
body: JSON.stringify({token: token.id}),
headers: {'Content-Type': 'application/json'}
});
});
</script>PayPal Integration
liquid
{% paypal_button price: product.price, item: product.name %}Mollie Payments
liquid
{{ order | payment_form, provider: 'mollie' }}Security Features
ReCAPTCHA
liquid
{% recaptcha site_key: 'your_recaptcha_site_key' %}
{% recaptcha_button 'Submit Form', site_key: 'your_site_key' %}Form with ReCAPTCHA:
liquid
{% form channels.contact, class: 'contact-form' %}
{% input 'name', required: true %}
{% input 'email', as: 'email', required: true %}
{% text_area 'message', required: true %}
{% recaptcha site_key: site.recaptcha_key %}
{% submit_tag 'Send Message' %}
{% endform %}CSRF Protection
All forms automatically include CSRF tokens:
liquid
{% form model %}
<!-- Automatic CSRF token included -->
{% endform %}Manual CSRF token:
liquid
<form method="post">
{% csrf_token %}
<!-- form fields -->
</form>Consent Management
{% consent_manager %}
GDPR-compliant cookie consent:
liquid
{% consent_manager %}
<!-- Renders cookie consent banner -->Custom Consent Configuration:
liquid
{% consent_manager
privacy_url: '/privacy-policy',
cookie_url: '/cookie-policy',
categories: 'necessary,analytics,marketing'
%}Consent-Aware Scripts
liquid
<!-- Script loads only with consent -->
{{ 'analytics.js' | asset_url | script_tag, consent: 'analytics' }}Practical Examples
Complete Search Page
liquid
<div class="search-page">
<h1>Search</h1>
<form action="/search" method="get" class="search-form">
<input
type="search"
name="q"
value="{{ params.q }}"
placeholder="Search products, pages, articles..."
required>
<div class="search-filters">
<label>
<input type="checkbox" name="in[]" value="products" {% if params.in contains 'products' %}checked{% endif %}>
Products
</label>
<label>
<input type="checkbox" name="in[]" value="pages" {% if params.in contains 'pages' %}checked{% endif %}>
Pages
</label>
<label>
<input type="checkbox" name="in[]" value="articles" {% if params.in contains 'articles' %}checked{% endif %}>
Articles
</label>
</div>
<button type="submit">Search</button>
</form>
{% if params.q %}
{% assign search_types = params.in | default: 'products,pages,articles' %}
{% search params.q, in: search_types %}
{% if search.results.size > 0 %}
<div class="results-header">
<p>{{ search.results.size }} results for "{{ params.q }}"</p>
</div>
<div class="search-results">
{% for result in search.results %}
<div class="result result-{{ result.type }}">
<h3><a href="{{ result.url }}">{{ result.title | highlight: params.q }}</a></h3>
<p class="excerpt">
{{ result.excerpt | highlight: params.q }}
</p>
<div class="result-meta">
<span class="type">{{ result.type }}</span>
{% if result.price %}
<span class="price">{{ result.price | money_with_currency }}</span>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="no-results">
<p>No results found for "{{ params.q }}"</p>
<p>Try different keywords or browse our categories.</p>
</div>
{% endif %}
{% endsearch %}
{% endif %}
</div>Login Page with Social OAuth
liquid
<div class="login-page">
<div class="login-container">
<h2>Sign In</h2>
<!-- Email/Password Login -->
{% form customer, class: 'login-form' %}
{% error_messages_for form_model %}
<div class="form-group">
{% input 'email', as: 'email', label: 'Email', required: true %}
</div>
<div class="form-group">
{% input 'password', as: 'password', label: 'Password', required: true %}
</div>
<div class="form-actions">
{% submit_tag 'Sign In', class: 'btn btn-primary btn-block' %}
<a href="/forgot-password" class="forgot-password">Forgot password?</a>
</div>
{% endform %}
<div class="social-login-separator">
<span>Or sign in with</span>
</div>
<!-- Social Login Options -->
<div class="social-login-buttons">
{% login_with 'google', text: 'Continue with Google', class: 'btn btn-google' %}
{% login_with 'facebook', text: 'Continue with Facebook', class: 'btn btn-facebook' %}
{% login_with 'github', text: 'Continue with GitHub', class: 'btn btn-github' %}
</div>
<p class="register-link">
Don't have an account? <a href="/register">Create one</a>
</p>
</div>
</div>Account Settings with OAuth Connections
liquid
<div class="account-settings">
<h2>Connected Accounts</h2>
<div class="oauth-connections">
<!-- Google -->
<div class="connection">
<div class="connection-info">
<strong>Google</strong>
{% if customer.google_connected %}
<span class="status connected">Connected as {{ customer.google_email }}</span>
{% else %}
<span class="status">Not connected</span>
{% endif %}
</div>
<div class="connection-actions">
{% if customer.google_connected %}
{% unlink_from 'google', text: 'Disconnect', class: 'btn btn-sm btn-danger' %}
{% else %}
{% login_with 'google', text: 'Connect', class: 'btn btn-sm btn-primary' %}
{% endif %}
</div>
</div>
<!-- Facebook -->
<div class="connection">
<div class="connection-info">
<strong>Facebook</strong>
{% if customer.facebook_connected %}
<span class="status connected">Connected</span>
{% else %}
<span class="status">Not connected</span>
{% endif %}
</div>
<div class="connection-actions">
{% if customer.facebook_connected %}
{% unlink_from 'facebook', text: 'Disconnect', class: 'btn btn-sm btn-danger' %}
{% else %}
{% login_with 'facebook', text: 'Connect', class: 'btn btn-sm btn-primary' %}
{% endif %}
</div>
</div>
</div>
</div>Contact Form with ReCAPTCHA
liquid
<div class="contact-section">
<h2>Contact Us</h2>
{% form channels.contact, class: 'contact-form' %}
{% error_messages_for form_model %}
<div class="form-row">
<div class="col-md-6">
{% input 'first_name', label: 'First Name', required: true %}
</div>
<div class="col-md-6">
{% input 'last_name', label: 'Last Name', required: true %}
</div>
</div>
<div class="form-group">
{% input 'email', as: 'email', label: 'Email', required: true %}
</div>
<div class="form-group">
{% text_area 'message', rows: 6, label: 'Message', required: true %}
</div>
<!-- ReCAPTCHA -->
<div class="form-group">
{% recaptcha site_key: site.recaptcha_key %}
</div>
{% submit_tag 'Send Message', class: 'btn btn-primary' %}
{% endform %}
</div>Best Practices
1. Secure API Keys
liquid
<!-- ✅ Good: Use site configuration -->
{{ site.stripe_public_key }}
<!-- ❌ Bad: Hardcode keys -->
{{ 'pk_live_XXXXXXXX' }}2. HTTPS for OAuth
All OAuth flows require HTTPS in production.
3. Validate Search Input
liquid
<!-- ✅ Good: Sanitize search query -->
{% assign safe_query = params.q | strip | truncate: 100 %}
{% search safe_query %}
<!-- ⚠️ Always validate user input -->4. Consent Before Tracking
liquid
<!-- ✅ Good: Respect consent -->
{{ 'analytics.js' | script_tag, consent: 'analytics' %}
<!-- ❌ Bad: Track without consent -->
{{ 'analytics.js' | script_tag }}Next Steps
- Forms - Form building and validation
- Multilingual - Internationalization
- Global Variables - Available drops
- Cloud Code - Custom server logic
Build advanced features with Nimbu!