How to Build a Quote of the Day Widget for Your Website
Why Add a Quote of the Day Widget?
A quote of the day widget is one of the highest-engagement micro-features you can add to a website. It gives returning visitors a reason to check back daily, boosts session time, and — when paired with a reliable API — requires almost no maintenance after initial setup. Whether you're building a productivity dashboard, a blog sidebar, or a SaaS landing page, rotating daily quotes add personality and perceived dynamism to otherwise static content.
The key is using a structured API rather than hardcoding quotes. Hardcoded arrays go stale, require deployments to update, and can't be filtered by category or language. An API-driven widget solves all three problems immediately.
What You Need Before You Start
To follow this guide you'll need: a free API key from qod.io, a basic understanding of JavaScript's Fetch API, and any website where you can insert a <script> block — no framework required. The approach works equally well in plain HTML, React, Vue, or any server-side templating language.
Sign up at qod.io to receive your API key. The free tier delivers one fresh quote per day per category, with optional filtering by tag (motivational, literary, philosophical, etc.). Rate limits on the free plan are generous enough for personal projects and low-traffic sites.
Fetching the Quote from the QOD API
The QOD API endpoint is straightforward. A GET request to https://api.qod.io/v1/quote with your key in the Authorization header returns a JSON object containing the quote text, author name, category, and a stable daily ID. Here's the minimal fetch call:
async function fetchDailyQuote() {
const res = await fetch('https://api.qod.io/v1/quote', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const data = await res.json();
return data.quote; // { text, author, category }
}
The response is cached server-side so every request within the same UTC day returns the identical quote. This means you can call the endpoint on every page load without worrying about inconsistency — a visitor refreshing the page sees the same quote, which is the expected UX for a daily widget.
Building the Widget HTML and CSS
Keep the widget markup minimal. A container div, a blockquote for the text, and a cite element for the author is all you need semantically. Here's the complete self-contained widget implementation:
<div id="qod-widget" style="
background:#1a1a2e;border-left:4px solid #6c63ff;
padding:20px 24px;border-radius:6px;max-width:520px;
font-family:Georgia,serif;">
<blockquote id="qod-text" style="
font-size:1.1rem;color:#e0e0e0;margin:0 0 12px;">
Loading…
</blockquote>
<cite id="qod-author" style="
font-size:.9rem;color:#9e9e9e;font-style:normal;">
</cite>
</div>
<script>
(async () => {
const q = await fetchDailyQuote();
document.getElementById('qod-text').textContent = `"${q.text}"`;
document.getElementById('qod-author').textContent = `— ${q.author}`;
})();
</script>
The inline styles make the widget fully portable — drop it into any page without touching your global stylesheet.
Caching the Response to Protect Your Rate Limit
Even though the API is fast, making a network request on every page load adds latency and consumes rate-limit quota unnecessarily. The solution is localStorage caching with a daily expiry. Store the fetched quote alongside a timestamp, and only hit the API again if the stored date differs from today's UTC date:
async function getDailyQuote() {
const stored = JSON.parse(localStorage.getItem('qod_cache') || '{}');
const today = new Date().toISOString().slice(0, 10);
if (stored.date === today) return stored.quote;
const quote = await fetchDailyQuote();
localStorage.setItem('qod_cache', JSON.stringify({ date: today, quote }));
return quote;
}
This pattern means the API is called once per browser per day, regardless of how many times the visitor loads the page. It's the same technique used in production by dashboard tools like Notion widgets and browser start-page extensions.
Filtering by Category for Contextual Relevance
The quote of the day widget becomes significantly more powerful when you match the quote category to your site's audience. Pass a category query parameter to the endpoint: ?category=motivational for fitness or productivity sites, ?category=literary for book blogs, or ?category=philosophical for education platforms. The QOD API supports per-category daily rotation, so two different categories always return two different quotes on the same day.
You can expose this as a user preference — store the chosen category in localStorage alongside the cached quote and re-fetch only when the category changes. This turns a simple widget into a lightly personalized feature with minimal engineering effort.
Deploying and Testing Your Widget
Before going live, test with your browser's network tab open. Confirm the API returns a 200 status, the JSON structure matches what your code expects, and the localStorage cache populates correctly on first load and is read on the second. Use the QOD sandbox endpoint (/v1/quote?preview=true) to force a fresh response during development without burning your daily cache.
For production, consider moving the API call to a lightweight serverless function (Vercel Edge Functions, Cloudflare Workers) so your API key never appears in client-side code. The serverless function fetches, caches in KV storage, and serves the quote as a public JSON endpoint — eliminating any client-side key exposure entirely. This is the architecture recommended for any public-facing quote of the day widget with meaningful traffic.