Google SEO Filter Sidebar

Adds a powerful SEO filter sidebar to Google Search with filetype, date range, site filter, keyword location, and more.

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         Google SEO Filter Sidebar
// @namespace    https://github.com/seo-sidebar
// @version      1.0.0
// @description  Adds a powerful SEO filter sidebar to Google Search with filetype, date range, site filter, keyword location, and more.
// @author       SEO Sidebar
// @match        https://www.google.com/search*
// @match        https://google.com/search*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
  'use strict';

  // ─── Prevent double injection ───────────────────────────────────────────────
  if (document.getElementById('seo-sidebar-root')) return;

  // ─── Styles ─────────────────────────────────────────────────────────────────
  const style = document.createElement('style');
  style.textContent = `
    @import url('https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=DM+Sans:wght@400;500;600&display=swap');

    #seo-sidebar-toggle {
      position: fixed;
      top: 50%;
      right: 0;
      transform: translateY(-50%);
      z-index: 99999;
      background: #1a1a2e;
      color: #e0e0ff;
      border: none;
      border-radius: 8px 0 0 8px;
      padding: 10px 6px;
      cursor: pointer;
      font-size: 18px;
      writing-mode: vertical-rl;
      letter-spacing: 2px;
      font-family: 'DM Mono', monospace;
      font-size: 11px;
      font-weight: 500;
      text-transform: uppercase;
      gap: 6px;
      display: flex;
      align-items: center;
      box-shadow: -2px 0 12px rgba(0,0,0,0.3);
      transition: background 0.2s, right 0.3s ease;
    }

    #seo-sidebar-toggle:hover {
      background: #16213e;
    }

    #seo-sidebar-toggle .toggle-arrow {
      writing-mode: horizontal-tb;
      font-size: 14px;
      margin-bottom: 6px;
    }

    #seo-sidebar-root {
      position: fixed;
      top: 0;
      right: -340px;
      width: 320px;
      height: 100vh;
      z-index: 99998;
      background: #0f0f1a;
      color: #e0e0ff;
      font-family: 'DM Sans', sans-serif;
      display: flex;
      flex-direction: column;
      box-shadow: -4px 0 30px rgba(0,0,0,0.5);
      transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
      border-left: 1px solid rgba(255,255,255,0.07);
    }

    #seo-sidebar-root.open {
      right: 0;
    }

    #seo-sidebar-root.open ~ #seo-sidebar-toggle {
      right: 320px;
    }

    .seo-header {
      padding: 18px 20px 14px;
      border-bottom: 1px solid rgba(255,255,255,0.08);
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .seo-header h2 {
      font-family: 'DM Mono', monospace;
      font-size: 12px;
      font-weight: 500;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: #7c7cff;
      margin: 0;
    }

    .seo-header span {
      font-size: 10px;
      color: rgba(224,224,255,0.35);
      font-family: 'DM Mono', monospace;
    }

    .seo-body {
      flex: 1;
      overflow-y: auto;
      padding: 16px 20px;
      display: flex;
      flex-direction: column;
      gap: 20px;
    }

    .seo-body::-webkit-scrollbar { width: 4px; }
    .seo-body::-webkit-scrollbar-track { background: transparent; }
    .seo-body::-webkit-scrollbar-thumb { background: rgba(124,124,255,0.3); border-radius: 2px; }

    .seo-section {
      display: flex;
      flex-direction: column;
      gap: 8px;
    }

    .seo-section-label {
      font-family: 'DM Mono', monospace;
      font-size: 10px;
      font-weight: 500;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      color: rgba(255,255,255,0.3);
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .seo-section-label::after {
      content: '';
      flex: 1;
      height: 1px;
      background: rgba(255,255,255,0.07);
    }

    .seo-input, .seo-select {
      width: 100%;
      background: rgba(255,255,255,0.05);
      border: 1px solid rgba(255,255,255,0.1);
      border-radius: 7px;
      color: #e0e0ff;
      font-family: 'DM Sans', sans-serif;
      font-size: 13px;
      padding: 9px 12px;
      outline: none;
      box-sizing: border-box;
      transition: border-color 0.2s, background 0.2s;
      appearance: none;
    }

    .seo-input:focus, .seo-select:focus {
      border-color: #7c7cff;
      background: rgba(124,124,255,0.08);
    }

    .seo-input::placeholder {
      color: rgba(224,224,255,0.25);
    }

    .seo-select {
      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%237c7cff' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
      background-repeat: no-repeat;
      background-position: right 12px center;
      padding-right: 32px;
      cursor: pointer;
    }

    .seo-select option {
      background: #1a1a2e;
      color: #e0e0ff;
    }

    .seo-date-row {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 8px;
    }

    .seo-date-wrap {
      display: flex;
      flex-direction: column;
      gap: 4px;
    }

    .seo-date-wrap small {
      font-size: 10px;
      color: rgba(224,224,255,0.3);
      font-family: 'DM Mono', monospace;
      padding-left: 2px;
    }

    input[type="date"].seo-input::-webkit-calendar-picker-indicator {
      filter: invert(0.7) sepia(1) saturate(3) hue-rotate(200deg);
      cursor: pointer;
    }

    .seo-chip-row {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
    }

    .seo-chip {
      background: rgba(255,255,255,0.05);
      border: 1px solid rgba(255,255,255,0.1);
      border-radius: 20px;
      padding: 5px 11px;
      font-size: 12px;
      cursor: pointer;
      color: rgba(224,224,255,0.6);
      font-family: 'DM Mono', monospace;
      transition: all 0.15s;
      user-select: none;
    }

    .seo-chip:hover {
      border-color: #7c7cff;
      color: #7c7cff;
    }

    .seo-chip.active {
      background: rgba(124,124,255,0.15);
      border-color: #7c7cff;
      color: #a0a0ff;
    }

    .seo-footer {
      padding: 16px 20px;
      border-top: 1px solid rgba(255,255,255,0.08);
      display: flex;
      flex-direction: column;
      gap: 8px;
    }

    .seo-btn {
      width: 100%;
      padding: 11px;
      border: none;
      border-radius: 8px;
      font-family: 'DM Sans', sans-serif;
      font-size: 13px;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.2s;
    }

    .seo-btn-primary {
      background: #7c7cff;
      color: #fff;
    }

    .seo-btn-primary:hover {
      background: #9090ff;
      transform: translateY(-1px);
      box-shadow: 0 4px 16px rgba(124,124,255,0.35);
    }

    .seo-btn-secondary {
      background: rgba(255,255,255,0.05);
      color: rgba(224,224,255,0.5);
      border: 1px solid rgba(255,255,255,0.08);
    }

    .seo-btn-secondary:hover {
      background: rgba(255,255,255,0.09);
      color: rgba(224,224,255,0.8);
    }

    .seo-query-preview {
      font-family: 'DM Mono', monospace;
      font-size: 11px;
      color: rgba(124,124,255,0.6);
      background: rgba(124,124,255,0.06);
      border: 1px solid rgba(124,124,255,0.15);
      border-radius: 6px;
      padding: 8px 10px;
      word-break: break-all;
      min-height: 36px;
      line-height: 1.6;
    }

    .seo-query-preview-label {
      font-size: 9px;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      color: rgba(255,255,255,0.2);
      font-family: 'DM Mono', monospace;
      margin-bottom: 4px;
    }

    .seo-toast {
      position: fixed;
      bottom: 24px;
      right: 24px;
      background: #1a1a2e;
      color: #a0a0ff;
      border: 1px solid rgba(124,124,255,0.3);
      border-radius: 8px;
      padding: 10px 16px;
      font-family: 'DM Mono', monospace;
      font-size: 12px;
      z-index: 999999;
      opacity: 0;
      transform: translateY(8px);
      transition: all 0.25s;
      pointer-events: none;
    }
    .seo-toast.show {
      opacity: 1;
      transform: translateY(0);
    }
  `;
  document.head.appendChild(style);

  // ─── Sidebar HTML ────────────────────────────────────────────────────────────
  const sidebar = document.createElement('div');
  sidebar.id = 'seo-sidebar-root';
  sidebar.innerHTML = `
    <div class="seo-header">
      <h2>⬡ SEO Filters</h2>
      <span>google operator builder</span>
    </div>
    <div class="seo-body">

      <div class="seo-section">
        <div class="seo-section-label">Keyword</div>
        <input class="seo-input" id="seo-keyword" type="text" placeholder='e.g. "best laptops 2024"' />
      </div>

      <div class="seo-section">
        <div class="seo-section-label">Keyword Location</div>
        <div class="seo-chip-row" id="seo-kw-location">
          <span class="seo-chip" data-val="intitle">intitle</span>
          <span class="seo-chip" data-val="inurl">inurl</span>
          <span class="seo-chip" data-val="intext">intext</span>
          <span class="seo-chip" data-val="inanchor">inanchor</span>
          <span class="seo-chip" data-val="allintitle">allintitle</span>
          <span class="seo-chip" data-val="allinurl">allinurl</span>
        </div>
      </div>

      <div class="seo-section">
        <div class="seo-section-label">Site / Domain</div>
        <input class="seo-input" id="seo-site" type="text" placeholder="e.g. reddit.com or .gov" />
      </div>

      <div class="seo-section">
        <div class="seo-section-label">Exclude Site</div>
        <input class="seo-input" id="seo-exclude-site" type="text" placeholder="e.g. pinterest.com" />
      </div>

      <div class="seo-section">
        <div class="seo-section-label">File Type</div>
        <div class="seo-chip-row" id="seo-filetype">
          <span class="seo-chip" data-val="pdf">PDF</span>
          <span class="seo-chip" data-val="doc">DOC</span>
          <span class="seo-chip" data-val="docx">DOCX</span>
          <span class="seo-chip" data-val="xls">XLS</span>
          <span class="seo-chip" data-val="xlsx">XLSX</span>
          <span class="seo-chip" data-val="ppt">PPT</span>
          <span class="seo-chip" data-val="csv">CSV</span>
          <span class="seo-chip" data-val="txt">TXT</span>
          <span class="seo-chip" data-val="xml">XML</span>
          <span class="seo-chip" data-val="json">JSON</span>
        </div>
        <input class="seo-input" id="seo-filetype-custom" type="text" placeholder="Or type custom filetype..." style="margin-top:6px" />
      </div>

      <div class="seo-section">
        <div class="seo-section-label">Date Range</div>
        <select class="seo-select" id="seo-date-preset">
          <option value="">— any time —</option>
          <option value="d">Past 24 hours</option>
          <option value="w">Past week</option>
          <option value="m">Past month</option>
          <option value="y">Past year</option>
          <option value="custom">Custom range...</option>
        </select>
        <div class="seo-date-row" id="seo-custom-date" style="display:none;margin-top:6px">
          <div class="seo-date-wrap">
            <small>From</small>
            <input class="seo-input" type="date" id="seo-date-from" />
          </div>
          <div class="seo-date-wrap">
            <small>To</small>
            <input class="seo-input" type="date" id="seo-date-to" />
          </div>
        </div>
      </div>

      <div class="seo-section">
        <div class="seo-section-label">Related / Cache</div>
        <div class="seo-chip-row" id="seo-special">
          <span class="seo-chip" data-val="related">related:</span>
          <span class="seo-chip" data-val="cache">cache:</span>
          <span class="seo-chip" data-val="info">info:</span>
        </div>
        <input class="seo-input" id="seo-special-val" type="text" placeholder="Enter URL or domain..." style="margin-top:6px;display:none" />
      </div>

      <div class="seo-section">
        <div class="seo-section-label">Exclude Words</div>
        <input class="seo-input" id="seo-exclude" type="text" placeholder='e.g. spam, ads, "click here"' />
      </div>

      <div class="seo-section">
        <div class="seo-section-label">Exact Phrase</div>
        <input class="seo-input" id="seo-exact" type="text" placeholder='e.g. content marketing tips' />
      </div>

      <div>
        <div class="seo-query-preview-label">Query Preview</div>
        <div class="seo-query-preview" id="seo-preview">—</div>
      </div>

    </div>
    <div class="seo-footer">
      <button class="seo-btn seo-btn-primary" id="seo-apply">⌕ Apply Filters</button>
      <button class="seo-btn seo-btn-secondary" id="seo-reset">✕ Reset All</button>
    </div>
  `;
  document.body.appendChild(sidebar);

  // ─── Toggle Button ───────────────────────────────────────────────────────────
  const toggle = document.createElement('button');
  toggle.id = 'seo-sidebar-toggle';
  toggle.innerHTML = `<span class="toggle-arrow">◀</span>SEO Filters`;
  document.body.appendChild(toggle);

  // ─── Toast ───────────────────────────────────────────────────────────────────
  const toast = document.createElement('div');
  toast.className = 'seo-toast';
  document.body.appendChild(toast);
  function showToast(msg) {
    toast.textContent = msg;
    toast.classList.add('show');
    setTimeout(() => toast.classList.remove('show'), 2200);
  }

  // ─── State ───────────────────────────────────────────────────────────────────
  let isOpen = false;
  let selectedFiletype = null;
  let selectedKwLocation = null;
  let selectedSpecial = null;

  // ─── Toggle open/close ───────────────────────────────────────────────────────
  toggle.addEventListener('click', () => {
    isOpen = !isOpen;
    sidebar.classList.toggle('open', isOpen);
    toggle.querySelector('.toggle-arrow').textContent = isOpen ? '▶' : '◀';
  });

  // ─── Chip logic ──────────────────────────────────────────────────────────────
  function setupChips(containerId, onSelect) {
    const container = document.getElementById(containerId);
    container.querySelectorAll('.seo-chip').forEach(chip => {
      chip.addEventListener('click', () => {
        const isActive = chip.classList.contains('active');
        container.querySelectorAll('.seo-chip').forEach(c => c.classList.remove('active'));
        if (!isActive) {
          chip.classList.add('active');
          onSelect(chip.dataset.val);
        } else {
          onSelect(null);
        }
        updatePreview();
      });
    });
  }

  setupChips('seo-filetype', v => { selectedFiletype = v; });
  setupChips('seo-kw-location', v => { selectedKwLocation = v; });
  setupChips('seo-special', v => {
    selectedSpecial = v;
    document.getElementById('seo-special-val').style.display = v ? 'block' : 'none';
  });

  // ─── Custom filetype overrides chip ─────────────────────────────────────────
  document.getElementById('seo-filetype-custom').addEventListener('input', () => {
    if (document.getElementById('seo-filetype-custom').value.trim()) {
      document.getElementById('seo-filetype').querySelectorAll('.seo-chip').forEach(c => c.classList.remove('active'));
      selectedFiletype = null;
    }
    updatePreview();
  });

  // ─── Date preset ─────────────────────────────────────────────────────────────
  document.getElementById('seo-date-preset').addEventListener('change', () => {
    const v = document.getElementById('seo-date-preset').value;
    document.getElementById('seo-custom-date').style.display = v === 'custom' ? 'grid' : 'none';
    updatePreview();
  });

  // ─── Live preview on all inputs ──────────────────────────────────────────────
  ['seo-keyword','seo-site','seo-exclude-site','seo-exclude','seo-exact','seo-special-val','seo-date-from','seo-date-to'].forEach(id => {
    const el = document.getElementById(id);
    if (el) el.addEventListener('input', updatePreview);
  });

  // ─── Build query string ──────────────────────────────────────────────────────
  function buildQuery() {
    const parts = [];
    const keyword = document.getElementById('seo-keyword').value.trim();
    const site = document.getElementById('seo-site').value.trim();
    const excludeSite = document.getElementById('seo-exclude-site').value.trim();
    const exact = document.getElementById('seo-exact').value.trim();
    const exclude = document.getElementById('seo-exclude').value.trim();
    const customFT = document.getElementById('seo-filetype-custom').value.trim();
    const specialVal = document.getElementById('seo-special-val').value.trim();
    const datePreset = document.getElementById('seo-date-preset').value;
    const dateFrom = document.getElementById('seo-date-from').value;
    const dateTo = document.getElementById('seo-date-to').value;

    if (exact) parts.push(`"${exact}"`);
    if (keyword) {
      if (selectedKwLocation) {
        parts.push(`${selectedKwLocation}:${keyword}`);
      } else {
        parts.push(keyword);
      }
    }
    if (site) parts.push(`site:${site}`);
    if (excludeSite) parts.push(`-site:${excludeSite}`);

    const ft = customFT || selectedFiletype;
    if (ft) parts.push(`filetype:${ft}`);

    if (exclude) {
      exclude.split(',').map(w => w.trim()).filter(Boolean).forEach(w => parts.push(`-${w}`));
    }
    if (selectedSpecial && specialVal) {
      parts.push(`${selectedSpecial}:${specialVal}`);
    }

    return { query: parts.join(' '), datePreset, dateFrom, dateTo };
  }

  function updatePreview() {
    const { query } = buildQuery();
    document.getElementById('seo-preview').textContent = query || '—';
  }

  // ─── Apply Filters ───────────────────────────────────────────────────────────
  document.getElementById('seo-apply').addEventListener('click', () => {
    const { query, datePreset, dateFrom, dateTo } = buildQuery();
    if (!query && !datePreset) { showToast('Add at least one filter first.'); return; }

    const params = new URLSearchParams(window.location.search);
    params.set('q', query || params.get('q') || '');

    // Date filter via tbs param
    if (datePreset && datePreset !== 'custom') {
      params.set('tbs', `qdr:${datePreset}`);
    } else if (datePreset === 'custom' && dateFrom && dateTo) {
      const fmt = d => d.replace(/-/g, '/');
      params.set('tbs', `cdr:1,cd_min:${fmt(dateFrom)},cd_max:${fmt(dateTo)}`);
    } else {
      params.delete('tbs');
    }

    params.delete('start'); // reset pagination
    window.location.href = `https://www.google.com/search?${params.toString()}`;
  });

  // ─── Reset ───────────────────────────────────────────────────────────────────
  document.getElementById('seo-reset').addEventListener('click', () => {
    ['seo-keyword','seo-site','seo-exclude-site','seo-exclude','seo-exact','seo-filetype-custom','seo-special-val'].forEach(id => {
      document.getElementById(id).value = '';
    });
    document.getElementById('seo-date-preset').value = '';
    document.getElementById('seo-date-from').value = '';
    document.getElementById('seo-date-to').value = '';
    document.getElementById('seo-custom-date').style.display = 'none';
    document.getElementById('seo-special-val').style.display = 'none';
    document.querySelectorAll('.seo-chip.active').forEach(c => c.classList.remove('active'));
    selectedFiletype = null; selectedKwLocation = null; selectedSpecial = null;
    updatePreview();
    showToast('Filters cleared.');
  });

  // ─── Auto-populate from current URL ──────────────────────────────────────────
  const currentQ = new URLSearchParams(window.location.search).get('q') || '';
  if (currentQ) {
    document.getElementById('seo-keyword').value = currentQ;
    updatePreview();
  }

})();