How to Add a Google Preferred Sources Card to Your Blog?

Google recently rolled out a new search feature called Preferred Sources.

If someone signs in with their Google account, they can now choose websites they trust. When they search, Google prioritizes those chosen sites in Top Stories and search results.

I started seeing a simple card at the end of articles on a few blogs:

Google Preferred Source Callout Banner

The text was simple:

“Want my posts to show up more often on Google? One click and Google will surface this site in your Top Stories.”

I liked the idea. Instead of asking people to join an email newsletter or follow on social media, it asks them to follow the site right inside Google Search.

I added this right here on surajkatwal.com.np across all blog posts, placing it right before the author bio.

When working on SEO and site structure, like in my WordPress to Astro internal linking case study, making it easy for readers to follow your site is just as useful as fixing your links.

Here is what this feature is, how it works, and how to build the card in Astro.


What is Google Preferred Sources?

Most people do not change their Google Search settings manually. But Google now gives publishers a direct way to prompt them.

When a reader marks your site as a preferred source:

  1. Top Stories priority: Your articles get a higher chance to appear in their Top Stories carousel.
  2. Preferred badge: A small “preferred” badge appears next to your site in search results.
  3. AI Overviews: In Google’s AI answers, your site also shows up with that badge.
  4. Synced everywhere: Because it links to their Google account, it works on mobile, desktop, and the Google app.

For independent blogs and niche sites, this is great. It helps you keep returning readers without relying on social media algorithms.


Why use a custom card instead of the default button?

In Google’s developer documentation, they give you a basic HTML snippet:

<script async src="https://news.google.com/swg/js/v1/publisher.js"></script>
<div google-add-preferred-source-btn></div>

The default button works, but it has a few problems:

  • It looks plain and easy to miss.
  • It does not explain what happens when you click it.
  • Most readers have no idea what “preferred source” means.

The custom card works better because the copy explains the benefit:

“Want my posts to show up more often on Google? One click and Google will surface this site in your Top Stories.”

It tells the reader exactly what to expect in one sentence.


The Card Design

Here is the card again:

Google Preferred Source Callout Banner

It has four parts:

  1. A white card with a subtle color gradient border.
  2. The Google “G” icon in a soft gray square.
  3. Two lines of clear text.
  4. A blue button with an external link arrow.

How it works under the hood?

Google gives publishers two ways to link this:

1. The JavaScript SDK

Google has a script:

<script async preferred-sources-control="manual" src="https://news.google.com/swg/js/v1/publisher.js"></script>

When you call preferredSource.addPreferredSource(), a small Google popup opens on your page. The user clicks confirm, and they stay on your site.

2. The Direct URL

Google also has a direct URL in their Source Preferences tool:

https://www.google.com/preferences/source?q=yourdomain.com

This opens Google’s preferences page with your site already selected.

The Hybrid Setup

The cleanest way is to use both.

Use a regular <a> link pointing to the direct URL. Then add a click handler in JavaScript. If Google’s script loaded, open the on-page popup. If an ad-blocker blocked the script, the link just opens the Google page in a new tab.

That way, the button always works.


The Astro Component

Here is the full component code (GooglePreferredSource.astro) for an Astro static setup:

---
interface Props {
  domain?: string;
  title?: string;
  subtitle?: string;
}

const {
  domain = 'surajkatwal.com.np',
  title = 'Want my posts to show up more often on Google?',
  subtitle = 'One click and Google will surface this site in your Top Stories.',
} = Astro.props;

const directUrl = `https://www.google.com/preferences/source?q=${domain}`;
---

<aside class="google-preferred-source-card" aria-label="Google Preferred Source">
  <div class="gps-left-content">
    <div class="gps-icon-wrap" aria-hidden="true">
      <svg viewBox="0 0 24 24" width="22" height="22" class="gps-google-icon">
        <path fill="#4285F4" d="M23.745 12.27c0-.7-.06-1.4-.19-2.07H12v4.51h6.6c-.29 1.52-1.14 2.82-2.4 3.68v3.05h3.88c2.27-2.09 3.66-5.17 3.66-9.17z"/>
        <path fill="#34A853" d="M12 24c3.24 0 5.95-1.08 7.93-2.91l-3.88-3.05c-1.08.72-2.45 1.16-4.05 1.16-3.12 0-5.77-2.1-6.72-4.93H1.25v3.15C3.26 21.36 7.33 24 12 24z"/>
        <path fill="#FBBC05" d="M5.28 14.27c-.25-.72-.38-1.49-.38-2.27s.13-1.55.38-2.27V6.58H1.25C.45 8.18 0 9.99 0 12s.45 3.82 1.25 5.42l4.03-3.15z"/>
        <path fill="#EA4335" d="M12 4.75c1.77 0 3.35.61 4.6 1.8l3.42-3.42C17.95 1.19 15.24 0 12 0 7.33 0 3.26 2.64 1.25 6.58l4.03 3.15c.95-2.83 3.6-4.98 6.72-4.98z"/>
      </svg>
    </div>
    <div class="gps-text-wrap">
      <div class="gps-title">{title}</div>
      <p class="gps-subtitle">{subtitle}</p>
    </div>
  </div>

  <div class="gps-action-wrap">
    <a
      href={directUrl}
      target="_blank"
      rel="noopener noreferrer"
      class="gps-btn"
      id="gps-preferred-btn"
    >
      <span>Add as preferred source</span>
      <svg class="gps-arrow" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <line x1="7" y1="17" x2="17" y2="7"></line>
        <polyline points="7 7 17 7 17 17"></polyline>
      </svg>
    </a>
  </div>
</aside>

<script is:inline async preferred-sources-control="manual" src="https://news.google.com/swg/js/v1/publisher.js"></script>
<script is:inline>
  (function() {
    function setupPreferredSource() {
      var btn = document.getElementById('gps-preferred-btn');
      if (!btn) return;

      btn.addEventListener('click', function(e) {
        if (window.preferredSource && typeof window.preferredSource.addPreferredSource === 'function') {
          e.preventDefault();
          window.preferredSource.addPreferredSource();
        }
      });

      var queue = self.PREFERRED_SOURCE = self.PREFERRED_SOURCE || [];
      queue.push(function(preferredSource) {
        preferredSource.init({ theme: 'light' });
      });
    }

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', setupPreferredSource);
    } else {
      setupPreferredSource();
    }
  })();
</script>

<style>
  .google-preferred-source-card {
    position: relative;
    background: #ffffff;
    border-radius: 14px;
    padding: 16px 22px;
    margin: 32px 0 28px 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    border: 2px solid transparent;
    background-image: linear-gradient(#ffffff, #ffffff), linear-gradient(135deg, #f97316 0%, #ec4899 35%, #6366f1 70%, #3b82f6 100%);
    background-origin: border-box;
    background-clip: padding-box, border-box;
    box-shadow: 0 4px 14px rgba(15, 23, 42, 0.04);
  }

  .gps-left-content {
    display: flex;
    align-items: center;
    gap: 16px;
    flex: 1;
    min-width: 0;
  }

  .gps-icon-wrap {
    width: 44px;
    height: 44px;
    min-width: 44px;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  }

  .gps-google-icon {
    display: block;
  }

  .gps-text-wrap {
    flex: 1;
    min-width: 0;
  }

  .gps-title {
    font-size: 15.5px;
    font-weight: 700;
    color: #0f172a;
    line-height: 1.35;
    margin: 0 0 3px 0;
  }

  .gps-subtitle {
    font-size: 13.5px;
    color: #64748b;
    line-height: 1.4;
    margin: 0;
  }

  .gps-action-wrap {
    flex-shrink: 0;
  }

  .gps-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    background: #2563eb;
    color: #ffffff !important;
    font-size: 13.5px;
    font-weight: 600;
    padding: 10px 18px;
    border-radius: 8px;
    text-decoration: none !important;
    white-space: nowrap;
    transition: all 0.15s ease-in-out;
    box-shadow: 0 1px 3px rgba(37, 99, 235, 0.25);
  }

  .gps-btn:hover {
    background: #1d4ed8;
    color: #ffffff !important;
    box-shadow: 0 4px 10px rgba(37, 99, 235, 0.35);
    transform: translateY(-1px);
  }

  .gps-arrow {
    display: inline-block;
    transition: transform 0.15s ease;
  }

  .gps-btn:hover .gps-arrow {
    transform: translate(1px, -1px);
  }

  @media (max-width: 640px) {
    .google-preferred-source-card {
      flex-direction: column;
      align-items: stretch;
      padding: 16px;
      gap: 14px;
    }

    .gps-left-content {
      align-items: flex-start;
      gap: 12px;
    }

    .gps-icon-wrap {
      width: 40px;
      height: 40px;
      min-width: 40px;
    }

    .gps-title {
      font-size: 14.5px;
    }

    .gps-subtitle {
      font-size: 12.5px;
    }

    .gps-action-wrap {
      width: 100%;
    }

    .gps-btn {
      width: 100%;
      padding: 10px 14px;
      font-size: 13px;
    }
  }
</style>

The Gradient Border in CSS

You do not need extra wrapper divs to get a rounded gradient border. The trick is background-clip:

border: 2px solid transparent;
background-image: 
  linear-gradient(#ffffff, #ffffff), 
  linear-gradient(135deg, #f97316 0%, #ec4899 35%, #6366f1 70%, #3b82f6 100%);
background-origin: border-box;
background-clip: padding-box, border-box;

The first white gradient fills the inside. The second color gradient fills the border area.


Where to put it?

On this blog, I placed it in src/pages/blog/[slug].astro right after the post content and share buttons, just before the author bio:

<!-- Inside src/pages/blog/[slug].astro -->
<article class="prose">
  <h1 class="post-title">{displayTitle}</h1>
  <div class="post-content">
    <Content />
  </div>

  <!-- Social share and Google Preferred Source card -->
  <div class="post-interactions">
    <ShareButtons />
    <GooglePreferredSource domain="surajkatwal.com.np" />
  </div>

  <!-- Author bio -->
  <div class="author-box">
    ...
  </div>
</article>

Putting it right before the author bio works best. The reader just finished reading the post. If they liked the content, they can follow the site on Google before reading the author bio.


What to check before adding it?

A few small details from Google’s documentation:

  1. Root domain only: You can only link root domains (yourdomain.com) or subdomains (news.yourdomain.com). Subfolders like yourdomain.com/blog do not work.
  2. Check eligibility first: Open google.com/preferences/source in your browser and search for your domain. If your site shows up in the list, you are good to go.
  3. Keep publishing: Google notes that sites that are inactive or rarely updated may get removed from the preferences tool over time.

Conclusion

Getting readers to follow your site inside Google Search is a neat feature.

Instead of a plain button, this simple card explains the benefit clearly, looks good on desktop and mobile, and gives people a quick way to see more of your work.

Want my posts to show up more often on Google?

One click and Google will surface this site in your Top Stories.

Add as preferred source
Suraj Katwal
Written by

Suraj Katwal

Digital marketer, data enthusiast, and developer based in Melbourne, originally from Nepal. I build web platforms, Flutter apps, and digital marketing campaigns. On the data side, I work with SQL and Python while growing into dbt and data pipeline tools.