Montag, 25 August 2025

Top 5 diese Woche

Ähnliche Tutorials

Seo Dashboard

Dieses Skript ist eine eigenständige Webanwendung, die eine umfassende Analyse von Keywords und Domains direkt im Browser ermöglicht. Es kombiniert PHP für die Weboberfläche mit einem Headless Browser (Puppeteer/Node.js) zur Datenerhebung, um präzisere Ergebnisse als einfache Curl-Abfragen zu liefern.

Funktionen:

  1. Keyword-Position: Ermittelt die aktuelle Platzierung deiner Domain für beliebige Keywords in Google.
  2. Konkurrenzanalyse: Zeigt die Top-Konkurrenten für jedes Keyword in den Suchergebnissen an.
  3. Sichtbarkeit: Übersicht über Top-10 und Top-100 Rankings, inkl. Historie.
  4. Meta-Daten Check: Prüft Title, Description und H1 deiner Domain.
  5. Page Speed: Misst die Ladezeit der Domain als einfacher Performance-Indikator.
  6. Trend-Charts: Visualisierung der Ranking-Entwicklung über die Zeit.
  7. Info-Boxen: Alle Ergebnisse werden übersichtlich in Infoboxen angezeigt, auflockerbar durch AJAX.
  8. Ein Dateiformat: PHP, HTML, CSS und JS sind in einer Datei integriert, einfach zu deployen.

Design:
Das Dashboard präsentiert Ergebnisse in klar strukturierten Boxen mit responsive Charts. Es ist schlicht, modern und eignet sich sowohl für einzelne Analysen als auch für laufende SEO-Monitorings.

<?php
// WARNUNG: Häufiges Scraping kann Google blockieren. Nutzung erfolgt auf eigene Verantwortung.

$dataFile = 'seo_full_history.json';
if(!file_exists($dataFile)) file_put_contents($dataFile,json_encode([]));

if(isset($_POST['action']) && $_POST['action']==='check') {
    $keywords = array_map('trim', explode(',', $_POST['keywords']));
    $domain = escapeshellarg($_POST['domain']);
    $resultsAll = [];

    foreach($keywords as $keywordRaw){
        $keyword = escapeshellarg($keywordRaw);

        $script = <<<JS
const puppeteer = require('puppeteer');

(async () => {
    const keyword = process.argv[2];
    const domain = process.argv[3];
    const browser = await puppeteer.launch({headless:true});
    const page = await browser.newPage();
    await page.goto('https://www.google.com/search?q=' + encodeURIComponent(keyword));
    
    const results = await page.evaluate(() => {
        let data = [];
        document.querySelectorAll('div.g').forEach(el => {
            const a = el.querySelector('a');
            const title = el.querySelector('h3') ? el.querySelector('h3').innerText : '';
            const url = a ? a.href : '';
            const desc = el.querySelector('.IsZvec') ? el.querySelector('.IsZvec').innerText : '';
            if(url) data.push({title,url,desc});
        });
        return data;
    });

    let position = null;
    let competitors = [];
    results.forEach((r,i)=>{
        if(r.url.includes(domain)) position = i+1;
        else competitors.push(r.url);
    });

    // Einfacher Meta-Check auf erster Treffer der Domain
    let meta = {};
    try{
        await page.goto('https://'+domain.replace(/https?:\/\//,''));
        meta.title = await page.title();
        meta.description = await page.$eval('meta[name="description"]',el=>el.content).catch(()=>'');
        meta.h1 = await page.$eval('h1',el=>el.innerText).catch(()=>'');
        const performanceTiming = JSON.parse(await page.evaluate(()=>JSON.stringify(window.performance.timing)));
        meta.loadTime = performanceTiming.loadEventEnd - performanceTiming.navigationStart;
    } catch(e){}

    await browser.close();
    console.log(JSON.stringify({keyword,position,competitors,meta}));
})();
JS;

        $tmpFile = tempnam(sys_get_temp_dir(),'seo').'.js';
        file_put_contents($tmpFile,$script);
        $output = shell_exec("node ".escapeshellarg($tmpFile)." $keyword $domain");
        unlink($tmpFile);

        $res = json_decode($output,true);
        $res['timestamp'] = date('Y-m-d H:i:s');
        $resultsAll[] = $res;

        $history = json_decode(file_get_contents($dataFile),true);
        $history[] = $res;
        file_put_contents($dataFile,json_encode($history));
    }

    header('Content-Type: application/json');
    echo json_encode($resultsAll);
    exit;
}

if(isset($_POST['action']) && $_POST['action']==='history'){
    echo file_get_contents($dataFile);
    exit;
}
?>

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Dreamcodes SEO Dashboard</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body{font-family:Arial,sans-serif;background:#f4f4f4;padding:20px;}
h1{text-align:center;}
.form-box{background:#fff;padding:20px;border-radius:8px;max-width:700px;margin:20px auto;}
.input-field{width:100%;padding:10px;margin:10px 0;border-radius:5px;border:1px solid #ccc;}
.button{padding:10px 20px;border:none;background:#007bff;color:#fff;border-radius:5px;cursor:pointer;}
.button:hover{background:#0056b3;}
.result-box{background:#fff;padding:20px;border-radius:8px;margin-top:20px;}
.info-box{background:#e9f7ef;border-left:5px solid #28a745;padding:10px;margin:10px 0;}
.chart-container{width:100%;max-width:900px;margin:20px auto;}
</style>
</head>
<body>
<h1>SEO Dashboard</h1>

<div class="form-box">
<input type="text" id="keywords" class="input-field" placeholder="Keywords eingeben, getrennt durch Kommas">
<input type="text" id="domain" class="input-field" placeholder="Domain eingeben">
<button class="button" onclick="checkSEO()">Analyse starten</button>
</div>

<div id="results" class="result-box" style="display:none;"></div>

<div class="chart-container">
<canvas id="trendChart"></canvas>
</div>

<script>
function checkSEO(){
    const keywords=document.getElementById('keywords').value;
    const domain=document.getElementById('domain').value;
    if(!keywords||!domain) return alert('Bitte Keywords und Domain eingeben.');
    const resultsDiv=document.getElementById('results');
    resultsDiv.style.display='block';
    resultsDiv.innerHTML='Bitte warten...';

    fetch('',{
        method:'POST',
        headers:{'Content-Type':'application/x-www-form-urlencoded'},
        body:'action=check&keywords='+encodeURIComponent(keywords)+'&domain='+encodeURIComponent(domain)
    }).then(r=>r.json()).then(data=>{
        let html='<h2>Ergebnisse</h2>';
        data.forEach(d=>{
            html+=`<div class="info-box">
<h3>${d.keyword}</h3>
<p>Position: ${d.position?d.position:'nicht gelistet'}</p>
<p>Konkurrenzdomains: ${d.competitors.slice(0,5).join(', ')}</p>
<p>Meta Title: ${d.meta.title}</p>
<p>Meta Description: ${d.meta.description}</p>
<p>H1: ${d.meta.h1}</p>
<p>Ladezeit: ${d.meta.loadTime?d.meta.loadTime+'ms':'n/a'}</p>
</div>`;
        });
        resultsDiv.innerHTML=html;
        loadTrendChart();
    });
}

function loadTrendChart(){
    fetch('',{
        method:'POST',
        headers:{'Content-Type':'application/x-www-form-urlencoded'},
        body:'action=history'
    }).then(r=>r.json()).then(history=>{
        const labels=[...new Set(history.map(h=>h.timestamp))];
        const keywords=[...new Set(history.map(h=>h.keyword))];
        const datasets=keywords.map(k=>{
            return {
                label:k,
                data: labels.map(l=>{
                    const entry=history.find(h=>h.keyword===k && h.timestamp===l);
                    return entry&&entry.position?entry.position:null;
                }),
                fill:false,
                borderColor:'#'+Math.floor(Math.random()*16777215).toString(16),
                tension:0.2
            };
        });
        const ctx=document.getElementById('trendChart').getContext('2d');
        new Chart(ctx,{
            type:'line',
            data:{labels,datasets},
            options:{responsive:true,plugins:{legend:{position:'bottom'}},scales:{y:{reverse:true,beginAtZero:false}}}
        });
    });
}
</script>

<div class="footer-box" style="text-align:center;margin-top:40px;padding:10px;background:#fff;border-radius:8px;">
<p>© <?php echo date("Y"); ?> Dreamcodes.net – Alle Rechte vorbehalten</p>
</div>

</body>
</html>
Vorheriges Tutorial
Nächstes Tutorial

Hier etwas für dich dabei?