Webflow Integration

Load DBindly collection data into your Webflow pages

Overview

DBindly integrates seamlessly with Webflow, allowing you to load dynamic collection data into your pages without any backend setup. You can display product catalogs, blog posts, team directories, or any other data stored in your DBindly collections.

There are three approaches to loading data in Webflow:

  1. DBindly Script (Recommended) - Use data attributes for automatic binding
  2. Vanilla JavaScript - Direct API calls for full control
  3. DBindly SDK - Enhanced features with caching and retries

Prerequisites

Before starting, you'll need:

  • A DBindly account with at least one collection
  • Your API key from the DBindly dashboard
  • A Webflow project with Editor or higher plan (for custom code)

Option 1: DBindly Script (Recommended)

The easiest way to load data is using the DBindly script with data attributes.

Step 1: Add the Script

Go to Project Settings then Custom Code then Head Code and add:

<script src="https://api.dbindly.com/dbindly.min.js"></script>
<script>
  DBindly.init({
    apiUrl: 'https://api.dbindly.com',
    apiKey: 'pk_live_your_api_key',
    cache: true,
    debug: false
  });
</script>

Step 2: Add Data Attributes to Elements

In Webflow Designer, add custom attributes to your elements:

For single data items (using data ID from URL):

<div dbind_load="{{dataId}}">
  <h1 dbind_data="title"></h1>
  <p dbind_data="description"></p>
  <img dbind_src="image" dbind_alt="title">
</div>

For collection lists:

<div dbind_collection="products" dbind_limit="12">
  <div dbind_template>
    <h3 dbind_data="name"></h3>
    <p dbind_data="price" dbind_format="currency"></p>
    <a dbind_href="link">View Product</a>
  </div>
</div>

See Data Attributes for the complete attribute reference.

Option 2: Vanilla JavaScript

For more control, use direct API calls in your Webflow custom code.

Fetching Collection Data

Add this to Page Settings then Custom Code then Before body tag:

<script>
(async function() {
  const API_URL = 'https://api.dbindly.com';
  const COLLECTION_SLUG = 'your-collection-slug';
 
  try {
    const response = await fetch(
      `${API_URL}/public/collections/${COLLECTION_SLUG}/data?limit=20&page=1`
    );
    const result = await response.json();
 
    // result.data = array of items
    // result.pagination = { page, limit, total, totalPages, hasMore }
 
    const container = document.querySelector('[data-products]');
 
    result.data.forEach(item => {
      const card = document.createElement('div');
      card.className = 'product-card';
      card.innerHTML = `
        <img src="${item.data.image}" alt="${item.data.name}">
        <h3>${item.data.name}</h3>
        <p class="price">$${item.data.price}</p>
      `;
      container.appendChild(card);
    });
 
  } catch (error) {
    console.error('Failed to load data:', error);
  }
})();
</script>

Fetching a Single Item

<script>
(async function() {
  const API_URL = 'https://api.dbindly.com';
 
  // Get data ID from URL parameter
  const params = new URLSearchParams(window.location.search);
  const dataId = params.get('id');
 
  if (!dataId) return;
 
  try {
    const response = await fetch(`${API_URL}/public/data/${dataId}`);
    const item = await response.json();
 
    // Populate your Webflow elements
    document.querySelector('[data-title]').textContent = item.data.title;
    document.querySelector('[data-description]').textContent = item.data.description;
    document.querySelector('[data-image]').src = item.data.image;
 
  } catch (error) {
    console.error('Failed to load item:', error);
  }
})();
</script>

Batch Fetching Multiple Items

<script>
(async function() {
  const API_URL = 'https://api.dbindly.com';
  const IDS = ['product-001', 'product-002', 'product-003'];
 
  try {
    const response = await fetch(`${API_URL}/public/batch`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        dataIds: IDS,
        fields: ['name', 'price', 'image'] // Optional: specific fields only
      })
    });
    const result = await response.json();
 
    // result.data = array of matching items
    // result.count = number of items returned
    console.log(result.data);
 
  } catch (error) {
    console.error('Failed to batch fetch:', error);
  }
})();
</script>

Option 3: DBindly SDK

If the SDK is published to a CDN, you can use it for built-in caching and retry logic:

<script type="module">
import { createDBindlyClient } from 'https://cdn.jsdelivr.net/npm/@dbindly/sdk';
 
const client = createDBindlyClient({
  apiUrl: 'https://api.dbindly.com',
  apiKey: 'pk_live_your_api_key',
  cache: true,
  cacheTTL: 300000, // 5 minutes
  retryAttempts: 3
});
 
// Fetch collection with pagination
const products = await client.fetchCollection('products', {
  page: 1,
  limit: 20,
  sort: 'price',
  order: 'asc'
});
 
// Fetch single item
const product = await client.fetchData('product-123');
 
// Batch fetch
const items = await client.fetchBatch(['id1', 'id2', 'id3']);
</script>

API Reference

Collection Endpoint

GET /api/public/collections/{slug}/data
ParameterTypeDefaultDescription
pagenumber1Page number
limitnumber20Items per page (1-100)
sortstringcreatedAtField to sort by
orderstringdescSort order (asc/desc)

Single Item Endpoint

GET /api/public/data/{dataId}

Batch Endpoint

POST /api/public/batch

Body:

{
  "dataIds": ["id1", "id2"],
  "fields": ["name", "price"]
}

Practical Examples

Dynamic Product Grid

In Webflow, create a container div with the attribute data-products:

<script>
(async function() {
  const container = document.querySelector('[data-products]');
  if (!container) return;
 
  // Show loading state
  container.innerHTML = '<p class="loading">Loading products...</p>';
 
  try {
    const response = await fetch(
      'https://api.dbindly.com/public/collections/products/data?limit=12'
    );
    const { data } = await response.json();
 
    container.innerHTML = data.map(product => `
      <div class="product-card">
        <img src="${product.data.image}" alt="${product.data.name}" loading="lazy">
        <h3>${product.data.name}</h3>
        <p class="price">$${product.data.price.toFixed(2)}</p>
        <a href="/product?id=${product.dataId}" class="btn">View Details</a>
      </div>
    `).join('');
 
  } catch (error) {
    container.innerHTML = '<p class="error">Failed to load products. Please refresh.</p>';
  }
})();
</script>

Blog Posts with Pagination

<script>
let currentPage = 1;
const limit = 6;
 
async function loadPosts(page) {
  const container = document.querySelector('[data-posts]');
  const pagination = document.querySelector('[data-pagination]');
 
  try {
    const response = await fetch(
      `https://api.dbindly.com/public/collections/blog-posts/data?page=${page}&limit=${limit}&sort=publishedAt&order=desc`
    );
    const result = await response.json();
 
    container.innerHTML = result.data.map(post => `
      <article class="post-card">
        <img src="${post.data.image}" alt="${post.data.title}">
        <h2>${post.data.title}</h2>
        <p>${post.data.excerpt}</p>
        <a href="/blog/${post.dataId}">Read More</a>
      </article>
    `).join('');
 
    // Update pagination
    pagination.innerHTML = `
      <button onclick="loadPosts(${page - 1})" ${page <= 1 ? 'disabled' : ''}>Previous</button>
      <span>Page ${page} of ${result.pagination.totalPages}</span>
      <button onclick="loadPosts(${page + 1})" ${!result.pagination.hasMore ? 'disabled' : ''}>Next</button>
    `;
 
    currentPage = page;
 
  } catch (error) {
    container.innerHTML = '<p>Failed to load posts.</p>';
  }
}
 
loadPosts(1);
</script>

Tips and Best Practices

1. Add Loading States

Always show a loading indicator while data is being fetched:

container.innerHTML = '<div class="skeleton-loader"></div>';

2. Handle Errors Gracefully

Display user-friendly error messages:

catch (error) {
  container.innerHTML = `
    <p class="error">Unable to load content.
    <button onclick="location.reload()">Try Again</button></p>
  `;
}

3. Use Lazy Loading for Images

Add loading lazy to images below the fold:

<img src="${item.image}" loading="lazy" alt="${item.name}">

4. Cache Data in Session Storage

For repeated page visits:

const cacheKey = `dbindly_${collectionSlug}_${page}`;
const cached = sessionStorage.getItem(cacheKey);
 
if (cached) {
  renderData(JSON.parse(cached));
} else {
  const data = await fetchData();
  sessionStorage.setItem(cacheKey, JSON.stringify(data));
  renderData(data);
}

5. Use URL Parameters for Dynamic Pages

Pass data IDs through URL parameters for detail pages:

// On list page
<a href="/product?id=${product.dataId}">View</a>
 
// On detail page
const dataId = new URLSearchParams(location.search).get('id');

Troubleshooting

CORS Errors

DBindly public endpoints allow requests from any origin. If you see CORS errors:

  • Ensure you are using the correct endpoint (/api/public/...)
  • Check that your API key is valid

Data Not Loading

  • Verify your collection slug matches exactly
  • Check browser console for error messages
  • Ensure your API key has the correct permissions

Slow Loading

  • Reduce the limit parameter
  • Enable caching in DBindly.init()
  • Use pagination instead of loading all data at once

Next Steps