├── .gitignore ├── README.md ├── function.js ├── index.js ├── package.json ├── public └── css │ └── styles.css ├── service_account.json └── views ├── index.pug ├── layout.pug └── result.pug /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | package-lock.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Google Indexing API 2 | **Cieszę się, że trafiłeś na to repozytorium. Jeżeli uważasz, że narzędzie jest przydatne to możesz postawić mi kawę na Buy Me A Coffe :)** 3 | 4 | Buy Me A Coffee 5 | 6 | Narzędzie pozwala na przesłanie hurtowej ilości adresów do indeksacji za pomocą Indexing API. Jeżeli nie wiesz czym jest Indexing API to więcej informacji znajdziesz [tutaj](https://developers.google.com/search/apis/indexing-api/v3/quickstart). 7 | 8 | Dlaczego warto z tego korzystać i dlaczego jest to lepsze niż przesyłanie adresów za pomocą Google Search Console? 9 | 10 | 11 | 12 | * możesz przesłać do 200 adresów dziennie 13 | * możesz przesłać do 100 adresów za jednym zamachem 14 | * adresy przesłane w ten sposób pojawiają się w indeksie znacznie szybciej niż za pomocą konwencjonalnych metod 15 | 16 | Tak o tym pisze Google: 17 | 18 | > Zalecamy używanie interfejsu Indexing API zamiast map witryny, ponieważ zapewnia to szybsze indeksowanie stron przez Googlebota niż w przypadku zaktualizowania mapy witryny i > zasygnalizowania tego faktu systemom Google. 19 | 20 | Korzystam z tego na różnych stronach (nowych, starych) i za każdym razem indeksacja jest błyskawiczna. Z reguły wszystkie adresy (np. 200 nowych podstron) pojawia się w indeksie do 24h po przesłaniu prośby o zaindeksowanie. 21 | 22 | ![indexing api](https://bootcampy.pl/wp-content/uploads/2022/03/18.png "Wykres z zaindeksowanymi adresami URL") 23 | 24 | ![indexing api](https://bootcampy.pl/wp-content/uploads/2022/03/19.png "Wykres z zaindeksowanymi adresami URL") 25 | 26 | ## No dobra, ale jak to odpalić? 27 | 28 | ### Utwórz konto usługi w Google Cloud Platform 29 | 30 | Żeby móc korzystać z interfejsu Indexing API najpierw musisz stworzyć konto usługi w Google Cloud Platform: 31 | 32 | * Wejdź na adres [https://console.developers.google.com/iam-admin/serviceaccounts](https://console.developers.google.com/iam-admin/serviceaccounts) 33 | 34 | * Kliknij **UTWÓRZ PROJEKT** 35 | 36 | ![utwórz projekt](https://bootcampy.pl/wp-content/uploads/2022/03/1.png "Utwórz projekt") 37 | 38 | * Wpisz nazwę swojego projektu i kliknij **UTWÓRZ** 39 | 40 | ![utwórz](https://bootcampy.pl/wp-content/uploads/2022/03/2.png "Utwórz") 41 | 42 | * Kliknij **UTWÓRZ KONTO USŁUGI** 43 | 44 | ![utwórz konto usługi](https://bootcampy.pl/wp-content/uploads/2022/03/3.png "Utwórz konto usługi") 45 | 46 | * Wpisz nazwę konta, resztę możesz pominąć 47 | 48 | ![nazwa konta](https://bootcampy.pl/wp-content/uploads/2022/03/4.png "Wpisz nazwę konta") 49 | 50 | * Zapisz nazwę (E-mail) konta usługi, bo będziesz musiał je dodać do GSC 51 | 52 | * Obok swojego konta usługi kliknij trzy kropki i **Zarządzaj kluczami** 53 | 54 | ![zarządzaj kluczami](https://bootcampy.pl/wp-content/uploads/2022/03/5.png "Zarządzaj kluczami") 55 | 56 | * Utwórz nowy klucz 57 | 58 | ![utwórz nowy klucz](https://bootcampy.pl/wp-content/uploads/2022/03/6.png "Utwórz nowy klucz") 59 | 60 | * Typ klucza JSON 61 | 62 | ![Typ klucza JSON](https://bootcampy.pl/wp-content/uploads/2022/03/7.png "Typ klucza JSON") 63 | 64 | * Klucz powinien zapisać się na dysku (plik json) 65 | 66 | ![pobranie klucza na dysk](https://bootcampy.pl/wp-content/uploads/2022/03/8.png "Pobranie klucza na dysk") 67 | 68 | 69 | Pobrany plik z kluczem zostanie wykorzystany później, jest on niezbędny do poprawnego działania narzędzia. 70 | 71 | 72 | ### Dodaj do projektu interfejs Indexing API 73 | 74 | * Przejdź do biblioteki interfejsów API 75 | 76 | ![biblioteka interfejsów API](https://bootcampy.pl/wp-content/uploads/2022/03/9.png "Biblioteka interfejsów API") 77 | 78 | * Wpisz w wyszukiwarce “indexing api” 79 | 80 | ![wyszukiwarka](https://bootcampy.pl/wp-content/uploads/2022/03/10.png "Wpisz w wyszukiwarce indexing API") 81 | 82 | * wybierz z listy Indexing API 83 | 84 | ![Indexing API](https://bootcampy.pl/wp-content/uploads/2022/03/11.png "Indexing API") 85 | 86 | * włącz interfejs 87 | 88 | ![Włącz interfejs](https://bootcampy.pl/wp-content/uploads/2022/03/12.png "Włącz interfejs") 89 | 90 | 91 | ### Dodaj konto usługi do GSC 92 | 93 | Jak masz już utworzone konto usługi to dodaj je jako **właściciela** do Google Search Console: 94 | 95 | * zaloguj się do Centrum dla webmasterów - [link](https://www.google.com/webmasters/verification/home) 96 | * wybierz usługę, do której chcesz dodać konto 97 | * dodaj wcześniej utworzone konto usługi 98 | 99 | ![gsc](https://bootcampy.pl/wp-content/uploads/2022/03/13.png "Dodaj konto usługi do GSC") 100 | 101 | ### Odpal narzędzie 102 | 103 | Żeby uruchomić narzędzie będziesz potrzebował zainstalowanego Node.js i npm, możesz to pobrać [tutaj](https://nodejs.org/en/). 104 | 105 | Jak masz już to ogarnięte to pobierz repozytorium. W folderze znajduje się plik service_account.json, jest on tylko poglądowy. Usuń go i wrzuć w jego miejsce wcześniej pobrany plik json z kluczem. Zmień nazwę pliku na service_account.json. 106 | 107 | Otwórz projekt np. w Visual Studio Code ([link](https://code.visualstudio.com/)) i w terminalu wpisz: 108 | ``` 109 | npm install 110 | ``` 111 | 112 | ![npm install](https://bootcampy.pl/wp-content/uploads/2022/03/16.png "npm install") 113 | 114 | Jak instalacja dobiegnie końca wpisz w terminalu: 115 | ``` 116 | node index.js 117 | ``` 118 | 119 | ![npm install](https://bootcampy.pl/wp-content/uploads/2022/03/17.png "npm install") 120 | 121 | W ten sposób odpalisz narzędzie, będzie ono dostępne pod adresem [http://localhost:8000/](http://localhost:8000/) 122 | 123 | W formularzu wklejasz adresy, które chcesz przesłać do indeksacji. 124 | 125 | ![formularz](https://bootcampy.pl/wp-content/uploads/2022/03/14.png "Formularz") 126 | 127 | Jeżeli wszystko zrobiłeś dobrze to po przesłaniu formularza powinieneś dostać response z kodem 200. Przy większej ilości adresów wygodniej to podejrzeć w konsoli przeglądarki. 128 | 129 | ![response](https://bootcampy.pl/wp-content/uploads/2022/03/15.png "Response") 130 | -------------------------------------------------------------------------------- /function.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var { google } = require("googleapis"); 3 | var key = require("./service_account.json"); 4 | 5 | async function indexingApi(urls, callback) { 6 | const jwtClient = new google.auth.JWT( 7 | key.client_email, 8 | null, 9 | key.private_key, 10 | ["https://www.googleapis.com/auth/indexing"], 11 | null 12 | ); 13 | const batch = urls.split(/\r?\n/g); 14 | 15 | jwtClient.authorize(function (err, tokens) { 16 | if (err) { 17 | console.log(err); 18 | return; 19 | } 20 | 21 | const items = batch.map((line) => { 22 | return { 23 | "Content-Type": "application/http", 24 | "Content-ID": "", 25 | body: 26 | "POST /v3/urlNotifications:publish HTTP/1.1\n" + 27 | "Content-Type: application/json\n\n" + 28 | JSON.stringify({ 29 | url: line, 30 | type: "URL_UPDATED", 31 | }), 32 | }; 33 | }); 34 | 35 | const options = { 36 | url: "https://indexing.googleapis.com/batch", 37 | method: "POST", 38 | headers: { 39 | "Content-Type": "multipart/mixed", 40 | }, 41 | auth: { bearer: tokens.access_token }, 42 | multipart: items, 43 | }; 44 | request(options, (err, resp, body) => { 45 | callback(body); 46 | }); 47 | }); 48 | } 49 | 50 | module.exports = { indexingApi }; 51 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // index.js 2 | 3 | /** 4 | * Required External Modules 5 | */ 6 | 7 | const express = require("express"); 8 | const path = require("path"); 9 | const bodyParser = require("body-parser"); 10 | 11 | const indexingApi = require("./function"); 12 | 13 | /** 14 | * App Variables 15 | */ 16 | 17 | const app = express(); 18 | const port = process.env.PORT || "8000"; 19 | 20 | /** 21 | * App Configuration 22 | */ 23 | 24 | app.set("views", path.join(__dirname, "views")); 25 | app.set("view engine", "pug"); 26 | app.use(express.static(__dirname + "/public")); 27 | 28 | app.use(bodyParser.urlencoded({ extended: true })); 29 | app.use(bodyParser.json()); 30 | 31 | /** 32 | * Routes Definitions 33 | */ 34 | 35 | app.get("/", (req, res) => { 36 | res.render("index", { title: "Indexing API" }); 37 | }); 38 | 39 | app.post("/result", function (req, res) { 40 | indexingApi.indexingApi(req.body.data, (data) => { 41 | res.render("result", { data: data }); 42 | }); 43 | }); 44 | 45 | /** 46 | * Server Activation 47 | */ 48 | 49 | app.listen(port, () => { 50 | console.log(`Listening to requests on http://localhost:${port}`); 51 | }); 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "index", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "nodemon ./index.js", 9 | "start": "node index.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "nodemon": "^2.0.15" 16 | }, 17 | "dependencies": { 18 | "body-parser": "^1.19.0", 19 | "express": "^4.17.1", 20 | "googleapis": "^92.0.0", 21 | "pug": "^3.0.2", 22 | "request": "^2.88.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /public/css/styles.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | } 6 | *, 7 | *:before, 8 | *:after { 9 | box-sizing: border-box; 10 | } 11 | body { 12 | font-family: "Roboto Mono", monospace; 13 | } 14 | h1 { 15 | margin-top: 0; 16 | text-align: center; 17 | } 18 | .home-container { 19 | height: 100vh; 20 | width: 100vw; 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | flex-direction: column; 25 | } 26 | .form-wrapper { 27 | max-width: 600px; 28 | width: 50%; 29 | padding: 40px; 30 | box-sizing: border-box; 31 | box-shadow: rgb(0 0 0 / 20%) 0px 0px 20px; 32 | border-radius: 4px; 33 | } 34 | textarea { 35 | width: 100%; 36 | height: 200px; 37 | padding: 8px; 38 | border-radius: 4px; 39 | border: 1px solid rgba(0, 0, 0, 0.1); 40 | background-color: rgb(245, 245, 245); 41 | font-family: "Roboto Mono", monospace; 42 | } 43 | textarea:focus { 44 | outline: none; 45 | } 46 | input[type="submit"] { 47 | background-color: rgb(0, 0, 0); 48 | color: rgb(255, 255, 255); 49 | padding: 8px 16px; 50 | cursor: pointer; 51 | border-radius: 4px; 52 | border: none; 53 | margin-top: 16px; 54 | font-family: "Roboto Mono", monospace; 55 | float: right; 56 | } 57 | code { 58 | display: block; 59 | width: 100%; 60 | height: 200px; 61 | padding: 8px; 62 | border-radius: 4px; 63 | border: 1px solid rgba(0, 0, 0, 0.1); 64 | background-color: rgb(245, 245, 245); 65 | overflow-y: scroll; 66 | margin-bottom: 16px; 67 | } 68 | .footer { 69 | padding: 40px; 70 | } 71 | -------------------------------------------------------------------------------- /service_account.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "", 3 | "project_id": "", 4 | "private_key_id": "", 5 | "private_key": "", 6 | "client_email": "", 7 | "client_id": "", 8 | "auth_uri": "", 9 | "token_uri": "", 10 | "auth_provider_x509_cert_url": "", 11 | "client_x509_cert_url": "" 12 | } 13 | -------------------------------------------------------------------------------- /views/index.pug: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block layout-content 4 | div.home-container 5 | div.form-wrapper 6 | h1 Indexing API 7 | form(action="/result" method="POST") 8 | textarea(name="data") 9 | br 10 | input(type="submit" value="Klik") 11 | div.footer autor: 12 | a(href="https://pl.linkedin.com/in/marek-folta%C5%84ski-a727aa144" target="_blank") Marek Foltański 13 | 14 | -------------------------------------------------------------------------------- /views/layout.pug: -------------------------------------------------------------------------------- 1 | block variables 2 | doctype html 3 | html 4 | head 5 | meta(charset="utf-8") 6 | link(rel="shortcut icon", href="/favicon.ico") 7 | link(rel='preconnect' href='https://fonts.googleapis.com') 8 | link(rel='preconnect' href='https://fonts.gstatic.com' crossorigin) 9 | link(href='https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&display=swap' rel='stylesheet') 10 | link(rel='stylesheet', href='/css/styles.css') 11 | meta(name="viewport", content="width=device-width, initial-scale=1, shrink-to-fit=no") 12 | meta(name="theme-color", content="#000000") 13 | title Indexing API 14 | body 15 | div#root 16 | block layout-content -------------------------------------------------------------------------------- /views/result.pug: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block layout-content 4 | div.home-container 5 | div.form-wrapper 6 | h1 Response 7 | code !{data} 8 | a(href="/") Wróć 9 | script. 10 | const string = !{JSON.stringify(data)}; 11 | console.log(string) 12 | div.footer autor: 13 | a(href="https://pl.linkedin.com/in/marek-folta%C5%84ski-a727aa144" target="_blank") Marek Foltański --------------------------------------------------------------------------------