<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Feedico</title>
    <description>The latest articles on DEV Community by Feedico (@feedico_8c6c4565ff094c285).</description>
    <link>https://dev.to/feedico_8c6c4565ff094c285</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3980784%2Faa3c5f70-f7f4-4583-a89d-f92ecad2b04b.png</url>
      <title>DEV Community: Feedico</title>
      <link>https://dev.to/feedico_8c6c4565ff094c285</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/feedico_8c6c4565ff094c285"/>
    <language>en</language>
    <item>
      <title>How I Normalized 74,000+ Scattered Coupon Feeds into a Single Real-Time API (And Built a Live Sandbox)</title>
      <dc:creator>Feedico</dc:creator>
      <pubDate>Fri, 12 Jun 2026 07:52:33 +0000</pubDate>
      <link>https://dev.to/feedico_8c6c4565ff094c285/how-i-normalized-74000-scattered-coupon-feeds-into-a-single-real-time-api-and-built-a-live-img</link>
      <guid>https://dev.to/feedico_8c6c4565ff094c285/how-i-normalized-74000-scattered-coupon-feeds-into-a-single-real-time-api-and-built-a-live-img</guid>
      <description>&lt;p&gt;Hey fellow devs,&lt;/p&gt;

&lt;p&gt;If you’ve ever dealt with affiliate networks like CJ, Awin, or Impact, you already know the pain. Each network speaks a completely different language. One gives you data in a bloated XML format, another uses a weirdly nested JSON structure, and the third one updates its endpoints whenever it feels like it.&lt;/p&gt;

&lt;p&gt;A few months ago, I got sick of writing separate custom parsers for every single network just to keep a coupon directory updated.&lt;/p&gt;

&lt;p&gt;So, I decided to build a unified middleware that does the heavy lifting: aggregating, parsing, de-duplicating, and normalizing tens of thousands of affiliate data points into a single, blazing-fast API.&lt;/p&gt;

&lt;p&gt;Today, I finally rolled out the live playground for it, and I wanted to share the architecture under the hood and how it works.&lt;/p&gt;

&lt;p&gt;The Problem: The "Affiliate Spaghetti Data"&lt;br&gt;
When you pull merchant vouchers globally, you face massive inconsistency:&lt;/p&gt;

&lt;p&gt;brand_id vs merchant_name: Network A calls it "Merchant XY", Network B calls it "Merchant XY LLC".&lt;/p&gt;

&lt;p&gt;Expiry Dates: Some networks use Unix timestamps, some use YYYY-MM-DD, and others just leave it null for ongoing deals.&lt;/p&gt;

&lt;p&gt;Tracking Links: Appending custom click parameters (subID or sid) without breaking the redirect chain is a nightmare.&lt;/p&gt;

&lt;p&gt;If your database can't handle this normalization dynamically, your frontend will either render broken links or stale data.&lt;/p&gt;

&lt;p&gt;The Architecture: How It Works&lt;br&gt;
I wanted the engine to be ridiculously fast. We currently track 41,452 unique merchants and over 74,296 active coupon codes.&lt;/p&gt;

&lt;p&gt;Here is the high-level flow of the engine:&lt;/p&gt;

&lt;p&gt;The Ingestion Layer: A fleet of cron jobs (Node.js/TypeScript) fetches raw data from master affiliate APIs at staggered intervals to prevent rate-limiting.&lt;/p&gt;

&lt;p&gt;The Normalization Pipeline: Every raw coupon object passes through a strict validation schema. Names are slugified, dates are unified to a standard ISO format, and expired tokens are instantly flagged.&lt;/p&gt;

&lt;p&gt;The Storage Strategy: Instead of blasting heavy relational JOIN queries every time a user types a word, everything is indexed efficiently so it handles full-text search instantly.&lt;/p&gt;

&lt;p&gt;The Frontend Challenge: Making It Look Like an API Dashboard&lt;br&gt;
I didn't want to build just another generic "coupon site" that looks like a spam factory from 2010. Since this is a B2B SaaS platform for developers and publishers, the UI needed to feel like a Live Sandbox.&lt;/p&gt;

&lt;p&gt;I spent the last few days cooking the frontend. It uses Server-Side Rendering (SSR) for the initial payload so search engine bots don't just see a blank loading spinner, but the search itself is fully reactive.&lt;/p&gt;

&lt;p&gt;When you type a keyword or a brand name (e.g., "travelup" or "hosting"), it instantly filters through the dataset with a 300ms debounce, updating the browser URL on the fly without refreshing the page.&lt;/p&gt;

&lt;p&gt;Here is a quick look at what the dashboard looks like right now:&lt;/p&gt;

&lt;p&gt;TypeScript&lt;br&gt;
// A sneak peek into how the omni-search handles both brand and content filtering&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filterCoupons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Coupon&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cleanQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;cleanQuery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Default fallback&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;brand_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cleanQuery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; 
    &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coupon_description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cleanQuery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check Out the Live Sandbox &lt;br&gt;
The project is called Feedico, and the live sandbox is officially up and running.&lt;/p&gt;

&lt;p&gt;You can break it, search for random brands, test the response speeds, or download sample raw CSV/XML exports directly from the UI:&lt;a href="https://feedico.io/live-coupon-feed" rel="noopener noreferrer"&gt;https://feedico.io/live-coupon-feed&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Feedico Live Coupon Feed &amp;amp; Sandbox&lt;/p&gt;

&lt;p&gt;If you want to see a specific query example in action (like how it renders pre-filtered data via SSR), check out this live endpoint instance: &lt;a href="https://feedico.io/live-coupon-feed" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What’s Next?&lt;br&gt;
I'm planning to open up the public API documentation next week so developers can just fetch clean, raw JSON streams by brand or keyword without scraping anything manually.&lt;/p&gt;

&lt;p&gt;I’d love to get some brutal feedback from the Dev.to community:&lt;/p&gt;

&lt;p&gt;How's the initial page load speed for you?&lt;/p&gt;

&lt;p&gt;Would you prefer Webhooks over standard REST polling for real-time coupon updates?&lt;/p&gt;

&lt;p&gt;Let me know in the comments below! Appreciate you guys reading. &lt;/p&gt;

</description>
      <category>api</category>
      <category>saas</category>
    </item>
  </channel>
</rss>
