DEV Community

Cover image for Embed Live South African Tender Data on Any Site — Free Widgets & JS SDK
mobius-crypt
mobius-crypt

Posted on

Embed Live South African Tender Data on Any Site — Free Widgets & JS SDK

You've probably embedded a GitHub stats card, a Wakatime badge, or a live crypto ticker on a personal project at some point. The idea is simple: pull live external data into your UI without owning the backend. Good DX, zero maintenance, real value.

Tenders SA just shipped exactly that — but for South African government procurement data. Four embeddable widgets, a JavaScript SDK, iFrame support, no API key, no account, no rate limits on the embed layer. Free forever.

Here's what's available, how to drop it in, and why it's actually interesting from a data-and-web perspective.


What Data Are We Talking About?

Tenders SA aggregates live tender data from South African government entities, municipalities, state-owned enterprises, and public procurement portals across all nine provinces. The platform normalises this into structured intelligence: active tenders, awarded contracts, sector breakdowns, company leaderboards, and provincial heatmaps.

The widgets expose a read-only slice of that data as embeddable UI components. Data refreshes every hour automatically.


The Four Widgets

Widget Best For Data Shown
Live Heatmap Portals, dashboards Tender density by province, real-time
Award Winners Feed News sites, feeds Scrolling recent contract award announcements
Top Companies Leaderboard Market intelligence tools Company rankings by sector award volume
Sector Trends Data journalism, analytics Tender volume + value charts by industry

All four are filterable by province (all 9 SA provinces supported) and sector (construction, ICT, professional services, electrical, civil engineering, and more).


Drop-In: iFrame Embed

The fastest possible integration. One tag, done.

<iframe
  src="https://tenders-sa.org/embed/heatmap"
  width="100%"
  height="400"
  frameborder="0"
  loading="lazy"
  title="TenderSA Intelligence Widget">
</iframe>
Enter fullscreen mode Exit fullscreen mode

You can swap heatmap for winners-feed, leaderboard, or sector-trends depending on which widget you want. Query params handle filtering — e.g.:

<iframe
  src="https://tenders-sa.org/embed/leaderboard?sector=construction&province=gauteng&theme=dark"
  width="100%"
  height="500"
  frameborder="0"
  loading="lazy"
  title="TenderSA Construction Leaderboard — Gauteng">
</iframe>
Enter fullscreen mode Exit fullscreen mode

Supports theme=light (default) and theme=dark. Works in any HTML environment: static sites, CMS embed blocks, email templates with webview links, you name it.


JavaScript SDK Embed

If you need tighter layout control or want to avoid iFrame sizing headaches, use the data-attribute SDK approach instead.

Step 1 — Add the script tag once, before </body>:

<script src="https://tenders-sa.org/tendersa-widget.js" async defer></script>
Enter fullscreen mode Exit fullscreen mode

Step 2 — Place the <div> wherever you want the widget to render:

<div
  data-tendersa-widget
  data-type="heatmap"
  data-province="western-cape"
  data-theme="dark">
</div>
Enter fullscreen mode Exit fullscreen mode

Available data-type values:

heatmap | winners-feed | leaderboard | sector-trends
Enter fullscreen mode Exit fullscreen mode

Available data-province values:

eastern-cape | free-state | gauteng | kwazulu-natal |
limpopo | mpumalanga | northern-cape | north-west | western-cape
Enter fullscreen mode Exit fullscreen mode

You can drop multiple <div> instances on the same page with different configurations — the single script handles all of them.


WordPress Integration

If you're building on WP, paste the JS snippet into your theme's functions.php to enqueue the script:

function tendersa_enqueue_widget() {
    wp_enqueue_script(
        'tendersa-widget',
        'https://tenders-sa.org/tendersa-widget.js',
        [],
        null,
        true // load in footer
    );
}
add_action( 'wp_enqueue_scripts', 'tendersa_enqueue_widget' );
Enter fullscreen mode Exit fullscreen mode

Then in any post, page, or block template:

<div
  data-tendersa-widget
  data-type="sector-trends"
  data-sector="construction"
  data-theme="light">
</div>
Enter fullscreen mode Exit fullscreen mode

Or use the iFrame embed inside a Custom HTML block in the Gutenberg editor — no theme edits required.


Shopify / Liquid

Add the script to your theme.liquid layout file before </body>:

<script src="https://tenders-sa.org/tendersa-widget.js" async defer></script>
Enter fullscreen mode Exit fullscreen mode

Then in any Section or Block .liquid file:

<div
  data-tendersa-widget
  data-type="winners-feed"
  data-province="{{ section.settings.province }}"
  data-theme="{{ section.settings.theme }}">
</div>
Enter fullscreen mode Exit fullscreen mode

You can wire province and theme to Shopify's Section Schema settings to make them editable in the Theme Customizer — no code changes needed per deployment.


React / Next.js

Since the SDK works via DOM data attributes, the cleanest React pattern is to load the script once (e.g. in _document.js or via next/script) and render the div as a standard component:

// components/TenderWidget.jsx
export default function TenderWidget({ type, province, sector, theme = 'light' }) {
  return (
    <div
      data-tendersa-widget
      data-type={type}
      data-province={province}
      data-sector={sector}
      data-theme={theme}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode
// Load script once in _app.js or layout.js
import Script from 'next/script';

export default function App({ Component, pageProps }) {
  return (
    <>
      <Script
        src="https://tenders-sa.org/tendersa-widget.js"
        strategy="lazyOnload"
      />
      <Component {...pageProps} />
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Then use it anywhere:

<TenderWidget type="leaderboard" sector="ict" province="gauteng" theme="dark" />
Enter fullscreen mode Exit fullscreen mode

RSS Feeds (Bonus)

If widgets are overkill for your use case and you just need a data feed, Tenders SA also publishes RSS feeds — filterable by province and category:

https://tenders-sa.org/rss/tenders/all
https://tenders-sa.org/rss/tenders/province/gauteng
https://tenders-sa.org/rss/tenders/category/construction
Enter fullscreen mode Exit fullscreen mode

Pipe these into your feed reader, n8n workflow, Zapier automation, or any RSS-capable aggregator.


Who Is This Actually Useful For?

  • South African tech bloggers covering procurement, GovTech, or public sector innovation — add live context to editorial content
  • Developer portfolio sites — if you work in the SA public sector space, this signals relevant domain knowledge
  • Industry news portals — construction, ICT, agriculture, engineering publications that want live market data without a data team
  • Side projects — building a SA business intelligence tool? This is free real-time procurement data to layer into your MVP

No Account. No Key. Just Paste.

There's no OAuth flow, no API key provisioning, no usage dashboard to log into. The widget builder at tenders-sa.org/publishers is a live configurator — pick your options, preview the output, copy the code.

If you need raw API access or more advanced customisation than the embeds allow, the Tenders SA team is contactable for that conversation.


Worth bookmarking if you're building anything in the SA public procurement or GovTech space. The free embed layer removes the usual "I need to scrape and host this myself" overhead entirely.


Built by Custom Logic Pty Ltd — South Africa 🇿🇦

Top comments (0)