Backlinks-teller voor een SaaS-dashboard, stap voor stap
Een werkende teller vereist één serverroute en één klein component. Deze handleiding bouwt beide, inclusief de foutstatussen die de meeste eerste versies vergeten.
Redactieteam AlfaLinks ·
Reikwijdte van deze handleiding
We gaan uit van een Node- of Python-backend en elk front-end framework. Elk verzoek hieronder raakt de gedocumenteerde API, en de basis-URL is die van je eigen merk: alfalinks.net/api.php.
Vijf stappen, in de volgorde waarin we ze zouden uitbrengen
01
1. Maak de sleutel aan en sla deze op als een geheim
Meld je aan via Google op /auth/google.php, kopieer de sk_-sleutel van de accountpagina en voeg deze toe aan je serveromgeving. Het front-end ziet deze nooit.
02
2. Voeg één proxyroute toe
Stel iets bloot zoals /internal/links?domain=... dat het domein valideert, onze API aanroept en alleen de velden retourneert die je UI gebruikt. Validatie is belangrijk omdat gebruikers van alles invoeren.
03
3. Begin met de gratis actie
De overview-actie kost niets, dus de eerste versie van de teller heeft helemaal geen facturatie risico. Ga pas naar betaalde acties wanneer een scherm dit nodig heeft.
04
4. Render drie statussen
Laden, gegevens en niet beschikbaar. Niet beschikbaar dekt HTTP 401, HTTP 402 en een netwerkfout, en het moet nooit een nul tonen.
05
5. Voeg het versheidslabel toe
Onze index wordt ongeveer maandelijks ververst. Een grijze regel met de tekst 'linkgegevens maandelijks bijgewerkt' voorkomt het supportticket dat begint met 'Ik heb gisteren een link toegevoegd'.
De proxyroute, in Node
Kort genoeg om in één scherm te lezen. De cache is hier een gewone Map; vervang deze door Redis zodra je meer dan één proces draait.
js
const cache = new Map();
const MONTH = 30 * 24 * 3600 * 1000;
app.get('/internal/links', async (req, res) => {
const domain = String(req.query.domain || '').toLowerCase().trim();
if (!/^[a-z0-9.-]+\.[a-z]{2,}$/.test(domain)) return res.status(400).json({ok:false});
const hit = cache.get(domain);
if (hit && Date.now() - hit.t < MONTH) return res.json(hit.v);
const r = await fetch(`https://alfalinks.net/api.php?action=overview&q=${domain}`);
if (!r.ok) return res.status(502).json({ok:false});
const v = await r.json();
cache.set(domain, {t: Date.now(), v});
res.json(v);
});
Een DR-badge toevoegen zodra de teller werkt
De teller is het makkelijke deel. De badge vereist één extra aanroep.
Voor een tabel met klantdomeinen stuur je één bulk_dr-verzoek met maximaal 2.000 domeinen in plaats van één aanroep per rij. Dit kost 1 credit ongeacht het aantal rijen, en de respons koppelt elk domein aan zijn 0-100 waarde, die je naast de gecachte overzichtgegevens opslaat.
Match domeinen op de genormaliseerde hostnaam. Verwijder het protocol, het pad en een voorloopende www, anders mis de helft van je rijen de lookup en tonen ze lege waarden.
Toon eerst een waarde, vraag dan pas om instellingen
Nieuwe gebruikers lezen zelden een installatiepagina. Ze willen zien of de functie de moeite waard is, en een backlinks-teller die een reëel cijfer toont, beantwoordt dat sneller dan enig formulier. Zet de waarde voorop. Configuratie komt op de tweede plaats.
Omdat de gratis overzichtactie geen sleutel vereist, kan je eerste scherm een cijfer tonen voordat de gebruiker überhaupt iets heeft geconfigureerd.
Wat heeft de eerste weergave nodig?
Slechts één domein en één gratis aanroep. Stel je een nieuwe gebruiker voor die zijn eigen site invoert tijdens de onboarding en de teller ziet verschijnen binnen dezelfde paginaweergave. Dat ene cijfer doet meer om de installatie te starten dan een lijst met stappen, dus houd de rest van de installatie erachter verborgen.
De gebruiker ziet wat hij krijgt voordat iemand om een kaart, een sleutel of een tweede formulier vraagt. Niets op de eerste weergave moet eruitzien als een poort.
Waar moet de installatieprompt staan?
Direct na het cijfer, niet ervoor. Een korte regel zoals 'Koppel een domein om dit elke maand te volgen' past onder de teller. Als dezelfde prompt boven het cijfer staat, lezen gebruikers het als een poort en vertrekken ze.
Houd bij welke gebruikers elke installatiestap voltooien. Een kleine funnel toont waar mensen stoppen, en een wijziging in de tekst verplaatst dat cijfer vaak meer dan een nieuwe functie zou doen.
Testen voor lancering
Test eerst de ongelukkige paden. Gelukkige paden testen zichzelf.
Trek de sleutel in staging in en bevestig dat de kaart 'niet beschikbaar' toont in plaats van nul. Leeg daarna een testbalans om een 402 te triggeren, en plak een ongeldige invoer zoals een domein met een protocol en een achterliggend pad om te bewijzen dat de validator dit afwijst voordat er credits worden uitgegeven.
E korte smoke test past in CI. Eén gratis overview-aanroep op nytimes.com, uitgevoerd elke nacht, vertelt je of de route en de sleutel nog werken.
Wie mag welk domein opvragen, en tegen welke kosten
Een teller die elke string accepteert is een open deur naar je balans. Bepaal wie wat mag vragen voordat de route live gaat, en schrijf het antwoord in de code in plaats van in een wiki-pagina die niemand opent.
Drie vragen komen altijd naar voren: welke domeinen, welke limiet, en waar de sleutel leeft.
Welke domeinen mag een gebruiker invoeren?
Alleen die waar de workspace een claim op heeft, plus alle publieke lookups die je hebt besloten aan te bieden. Stel dat een workspace twee sites bezit. De route kan die twee accepteren en alles anders afwijzen met een duidelijke boodschap, waardoor één tenant geen credits uitgeeft aan domeinen die niet van hem zijn.
De hostnaamcheck in de route is het minimum. Het bewijst dat de invoer eruitziet als een domein, niet dat de gebruiker het bezit, dus houd de claimlijst in je eigen database als een aparte tabel.
Hoe voorkom je dat één gebruiker de balans leegtrekt?
Stel een quota per workspace in je eigen opslag in en tel daar aanroepen. De balans aan onze kant is één voorgekochte pool, dus die kan je niet vertellen welke klant wat heeft uitgegeven. De lookup-pagina-opmerkingen behandelen de publieke kant van hetzelfde probleem. Wanneer een workspace zijn limiet bereikt, retourneer je een eenvoudige boodschap en laat de cache doorgaan met antwoorden met wat hij al vasthoudt.
Kies de limiet uit de rekenkunde in de per-seat-opmerkingen, niet uit een gok, en herzie het wanneer een plan verandert. Test de route met een tweede workspace voordat je het quota vertrouwt.
Moet de browser de sleutel ooit vasthouden?
Nee. De sleutel leeft op je server, en de browser roept je route aan. Die splitsing is ook wat een quota mogelijk maakt, omdat elke gefactureerde aanroep door code gaat die je beheerst. Als een sleutel ooit in een geleverde bundle verschijnt, draai hem dezelfde dag om en controleer de balanslog voor aanroepen die je niet hebt gedaan. Sommige teams slaan de sleutel op in een configuratiebestand dat het front-end leest tijdens het bouwen, en dat bestand eindigt in de bundle. Houd de sleutel buiten alles wat de build-step kan zien, en controleer de geleverde bestanden een keer voor elke release.
De gratis acties kunnen worden aangeroepen vanaf een publieke pagina zonder sleutel, en dat is de enige situatie waarin de browser direct met de API kan praten.
Wat de teller moet zeggen, en wat hij niet moet zeggen
Zeg minder dan je weet. Een teller gelabeld als 'backlinks' nodigt uit tot de vraag 'waarom toont Ahrefs een ander cijfer?', en het eerlijke antwoord is dat twee crawlers twee verschillende delen van het web zien.
Label het cijfer liever met de bron en de maand. Iets als 'Verwijzende domeinen, AlfaLinks-index, oktober 2026' is langer, maar het stopt het argument voordat het begint en het leest goed in een klein kaartje.
Rond af voor weergave. Een gebruiker die maandag 12.481 ziet en vrijdag 12.481, vertrouwt de tool meer dan iemand die jitter ziet, en onze maandelijkse verfrissing geeft je die stabiliteit gratis.
Als je de 0-100 waarde er naast wilt, lees dan eerst de opmerkingen over een backlinks-score. Het is onze eigen metric, dus benoeming is belangrijk.
Foutstatussen en wat de UI doet
HTTP-codes zijn die de API retourneert; de UI-kolom is ons voorstel.
Signaal
Betekenis
Wat de gebruiker ziet
Wat jij doet
HTTP 401
Ontbrekende of slechte sleutel
'Linkgegevens niet beschikbaar'
Pagina jezelf: deploy bug
HTTP 402
Credits opgebruikt
'Linkgegevens niet beschikbaar'
Vul aan met USDT (TRC-20)
ok: false
Verzoek afgewezen
Inline retry-link
Log het domein en de actie
Time-out
Netwerkprobleem
Gecachte waarde als je die hebt
Probeer het één keer opnieuw, en verhoog daarna de interval
De teller eerlijk houden in support en logs
Een teller faalt veel stiller dan luidruchtig. Log genoeg om de vraag te beantwoorden die een klant volgende stelt, en houd persoonsgegevens volledig buiten de log. Korte regels winnen. Een regel die een supportvraag beantwoordt, bespaart meer tijd dan enige alert die je kunt schrijven.
De meeste supportthreads over een teller gaan over één van drie vragen, dus plan de log daarop. Houd die drie vragen in je runbook, naast de stappen voor het draaien van een sleutel.
Wat moet elke logregel registreren?
De actie, het domein, de statuscode, de cacheleeftijd en de creditbalans die terugkwam. Die vijf velden beantwoorden de meeste supportvragen. Stel een gebruiker vraagt waarom zijn teller een oud cijfer toont. De cacheleeftijd en de indexmaand vertellen je of het probleem de cache of het label is.
Laat de API-sleutel weg uit elke regel, inclusief foutsporen. Masker hem bij de logger, omdat één gelekte regel de hele account kan leegtrekken.
Hoe weet je dat de teller elke week gezond is?
Houd drie cijfers in de gaten: het aandeel niet-beschikbare statussen, de trend van de creditbalans en de cache hit rate. Een plotselinge sprong in niet-beschikbare statussen wijst meestal op een sleutel- of balansprobleem. Een langzame daling in de balans wijst meestal op een cache sleutel die te specifiek is.
Elke meting heeft een andere oplossing, vandaar dat één dashboard-tegel voor allemaal zelden iemand helpt. Zet de drie metingen op één regel in je wekelijkse notitie, met de laatste waarde en de wijziging sinds de vorige week. Cijfers geïsoleerd lezen nodigt uit tot gissingen, terwijl een korte trend het gesprek bij dezelfde feiten houdt.