← Back to Blog
TutorialJanuary 12, 20256 min read

How to Add Merchant Logos to Your Fintech App

Merchant logos make bank transactions instantly recognizable. Here's how to get high-quality logos and display them in your React or Next.js app.

Open any modern banking app — Revolut, Monzo, N26 — and you'll see merchant logos next to every transaction. It's a small detail that makes a huge difference in user experience. Without logos, your transaction list is a wall of text. With logos, users can scan and find transactions instantly.

Why Merchant Logos Matter

Research from neobanks shows that merchant logos in transaction feeds:

  • Reduce support tickets — Users can identify transactions without calling support to ask "what's this charge?"
  • Increase engagement — Visually rich feeds keep users in the app longer
  • Build trust — A polished UI signals a professional, trustworthy product
  • Speed up recognition — Humans process images 60,000x faster than text

Before & After: The Visual Impact

Here's what a transaction list looks like without vs. with merchant logos:

Without logos
AMZN MKTP US*2K1AB
Jan 15
-$49.99
UBER *TRIP HELP.UBER
Jan 15
-$24.50
SQ *SWEETGREEN DOWNT
Jan 14
-$14.25
With logos
A
Amazon
Shopping
-$49.99
U
Uber
Transportation
-$24.50
S
Sweetgreen
Food & Drink
-$14.25

How to Get Merchant Logos

There are three common approaches to getting merchant logos:

Option 1: Favicon Scraping (Unreliable)

The simplest approach is to extract the merchant's domain and fetch its favicon. Services like Google's favicon API or DuckDuckGo's icon service can help:

// Google favicon API (low resolution, often blurry)
const faviconUrl = `https://www.google.com/s2/favicons?domain=${domain}&sz=64`;

// Problems:
// 1. You need to know the domain (hard to extract from "AMZN MKTP US*2K1AB")
// 2. Many favicons are 16x16 or 32x32 — too small for mobile apps
// 3. Some merchants don't have favicons at all
// 4. Rate limits and reliability issues

Option 2: Manual Logo Database (Doesn't Scale)

Some teams maintain their own logo database. This works for the top 100 merchants but falls apart quickly: you need to handle different sizes, formats, dark/light mode variants, and keep up with rebrands. It's a full-time job.

Option 3: Transaction Enrichment API (Recommended)

The best approach is to use a transaction enrichment API that returns logos as part of the enrichment response. You get the merchant name, category, and logo in a single API call.

// Easy Enrichment returns logo_url with every response
const result = await fetch('https://api.easyenrichment.com/enrich', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    description: 'AMZN MKTP US*2K1AB0C9Z',
    amount: 49.99,
  }),
}).then(r => r.json());

console.log(result.logo_url);
// "https://logo.easyenrichment.com/amazon.com"
// High-res, CDN-cached, always available

Implementing Logos in React / Next.js

Here's a production-ready React component for displaying transaction logos with fallbacks:

import { useState } from 'react';
import Image from 'next/image';

interface MerchantLogoProps {
  logoUrl?: string;
  merchantName: string;
  size?: number;
}

export function MerchantLogo({
  logoUrl,
  merchantName,
  size = 40,
}: MerchantLogoProps) {
  const [hasError, setHasError] = useState(false);

  // Generate a consistent color from merchant name
  const getColor = (name: string) => {
    const colors = [
      'bg-blue-500', 'bg-green-500', 'bg-purple-500',
      'bg-orange-500', 'bg-pink-500', 'bg-indigo-500',
    ];
    let hash = 0;
    for (let i = 0; i < name.length; i++) {
      hash = name.charCodeAt(i) + ((hash << 5) - hash);
    }
    return colors[Math.abs(hash) % colors.length];
  };

  if (!logoUrl || hasError) {
    // Fallback: colored circle with initial
    return (
      <div
        className={`${getColor(merchantName)} rounded-xl flex items-center
          justify-center text-white font-bold`}
        style={{ width: size, height: size, fontSize: size * 0.4 }}
      >
        {merchantName.charAt(0).toUpperCase()}
      </div>
    );
  }

  return (
    <Image
      src={logoUrl}
      alt={merchantName}
      width={size}
      height={size}
      className="rounded-xl object-contain bg-white"
      onError={() => setHasError(true)}
    />
  );
}

Using the Component in a Transaction List

interface Transaction {
  id: string;
  merchant_name: string;
  category: string;
  amount: number;
  date: string;
  logo_url?: string;
}

function TransactionList({ transactions }: { transactions: Transaction[] }) {
  return (
    <div className="divide-y divide-zinc-800">
      {transactions.map((txn) => (
        <div key={txn.id} className="flex items-center gap-3 py-3">
          <MerchantLogo
            logoUrl={txn.logo_url}
            merchantName={txn.merchant_name}
          />
          <div className="flex-1 min-w-0">
            <div className="font-medium text-white truncate">
              {txn.merchant_name}
            </div>
            <div className="text-sm text-zinc-500">{txn.category}</div>
          </div>
          <div className="text-right">
            <div className="font-medium text-white">
              {`-$${txn.amount.toFixed(2)}`}
            </div>
            <div className="text-sm text-zinc-500">{txn.date}</div>
          </div>
        </div>
      ))}
    </div>
  );
}

Performance Tips

  • Use Next.js Image component: It handles lazy loading, responsive sizes, and format optimization automatically.
  • Add logo URLs to next.config.js: Whitelist the logo CDN domain in images.remotePatterns for Next.js image optimization.
  • Store logo URLs in your database: Don't call the enrichment API on every page load. Store the logo URL when you first enrich the transaction.
  • Always implement a fallback: Even the best logo service won't cover 100% of merchants. The colored-initial fallback keeps your UI consistent.
  • Preload above-the-fold logos: Use priority prop on the first 5-10 logos to eliminate layout shift.

Next.js Configuration

// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'logo.easyenrichment.com',
        pathname: '/**',
      },
    ],
  },
};

Get Merchant Logos with Easy Enrichment

Every API response includes a high-resolution merchant logo URL, along with the merchant name, category, and 15+ other fields. Start free with 500 requests/month.