When you do something with web-hooks, there comes a time you run into problems. You need a service in between. For example this Blog runs with Ghost. The Ghost-Blogging-Platform is relatively new, and they introduced web-hooks a while ago. For example if you publish an post you can trigger something else.
This could be a tweet on Twitter, an old-school E-Mail or you can even let an LED Blink on an Arduino which runs Blynk.
One thing is that if you have an Blog you want to be found by google. The google bot visits your site dependent on many factors. But you can tell the Google-Bot that you have updated your content or released a new blog post.
If you're already a pro, skip the beginner intro.
Introduction for Beginners
This is done via the Google Indexing API.
Unfortunately this is what you need but this is not how it works. Ghost supports Webhooks, basically a webhook is a call to another website, in this call you also can deliver some information. The information delivery is usually handled via a json. A JSON is just structured data. Here is the JSON Standard: https://www.json.org/json-en.html
And this is how a JSON would look like:
{
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 27,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [],
"spouse": null
}
You have attributes and data. {}
is a dictionary like a telephone book and []
is just a list. And then of course you can put a list in a dict and that dict in a dict an so on.
The problem we face now is that Google don't know what to do with the JSON from Ghost. We need a middleman who translates all that stuff. And here comes all that fancy services you may have heard of in play.
Like: Zapier - well I don't really like Zapier, I really like something self hosted, like n8n.
This is how it would look like with n8n:
Connecting Webhooks
Good Video Tutorial: https://www.youtube.com/watch?v=ovlxledZfM4
So imagine you have already a n8n.io instance up and running. You log into your n8n-instance and then it will look something like this:
Now we know that Ghost supports web hooks. Ghost Web-hook Documentation: https://ghost.org/docs/api/v3/webhooks/. There we have site.changed
post.edited
, post.published
- I think post.published
sounds really good. You want to tell Google that you've just published a new post and the google bot should take a look at it.
- Now press the big red plus button. Go to the Trigger-Tab and type Web-hook.
- There is a menu telling you something about authentication etc. Just click at "Web-hook URLs"
- Change
HTTP-Method
toPOST
- Copy the url it will look something like this: http://n8n.example.com/webhook/12348239-asdf-4df-a920ae-ee83sdfj29b
- Now go to your Ghost Admin Menu:
Integrations --> + Add custom Integration
click on that - I'll call mine
n8n
Call it like: Notify Google
on Target URL, put your URL you copied from the n8n Web-hook Node.
Test your Web-hook with Curl on the command line:
curl -X POST -H 'Content-type: application/json' --data '{"text":"Test kekw"}' https://n8n.example.com/webhook/c8fa890f-218d-932f-a0ae-7b1cd66ee77b
First I got this error message:
{"code":404,"message":"The requested webhook "POST c8fa890f-218d-932f-a0ae-7b1cd66ee77b" is not registered."
Be sure that you press the button on the top right "Execute Node" then the node is waiting for a POST request.
curl -X POST -H 'Content-type: application/json' --data '{"text":"Test kekw"}' https://n8n.example.com/webhook-test/c8fa890f-218d-932f-a0ae-7b1cd66ee77b
If that web-hook gets triggered by the web-hook you'll see that Ghost sends the entire Blog-Entry-JSON. We only need the URL from the JSON: ['body']['post']['current']['url']
You can use this JSON for testing and sending it with curl to your n8n-webhook URL:
{
"post": {
"current": {
"url": "https://www.example.com/but-first-coffee/"
}
}
}
Your curl would look like this:
curl -X POST -H 'Content-type: application/json' --data '{
"post": {
"current": {
"url": "https://www.exmaple.com/but-first-coffee/"
}
}
}' https://n8n.example.com/webhook-test/bbabab98-2934-4328-1337-34892asfj109
Now we have to extract the data and notify Google that the post has updated. For that we Create a new Node called "HTTP Request".
Google expects an JSON which looks like that:
{
"url": "content_location",
"type": "URL_UPDATED"
}
Now click at the cogs. Add Expression
. Then on Current Node --> Input Data --> JSON --> body --> post --> current --> url
(to see the url you have to scroll down a bit)
The Expression should look like this:
{{$node["Webhook"].json["body"]["post"]["current"]["url"]}}
In the type field just type: URL_UPDATED
.
If you execute this node you'll see the following:
ERROR: 401 - {"error":{"code":401,"message":"Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.","status":"UNAUTHENTICATED"}}
We have to send some credentials to "login". The error message tells us, that we need an OAuth 2 access token.
Getting the Google OAuth2 Access token.
First you need to setup this: https://developers.google.com/search/apis/indexing-api/v3/prereqs
Then this here: https://developers.google.com/identity/protocols/oauth2
Here is a tutorial from google how to create OAuth2: https://developers.google.com/adwords/api/docs/guides/authentication
You need the:
- Client ID
- Client Secret
The rest is always the same:
If you got the error, that you press the connect button but no popup pops up. Clear all cookies or use Incognito-Tab and try again. And your browser should allow popups for your n8n instance.
Be sure also to set Auth URI Query Parameter
to:
access_type=offline&prompt=consent
otherwise you will get an Error: ERROR: No refresh token
.
(https://developers.google.com/identity/protocols/oauth2/web-server)
Everything to copy paste:
Authorization URL: https://accounts.google.com/o/oauth2/auth
Access Token URL: https://oauth2.googleapis.com/token
Scope: https://www.googleapis.com/auth/webmasters
On Googles Site:
Redirect URLS: https://sub.example.com/rest/oauth2-credential/callback
Javascript Sources: https://sub.example.com
- URL for HTTP Request Node:
https://indexing.googleapis.com/v3/urlNotifications:publish
Finishing up
Your HTTP Request should look like this:
Complete JSON to import in n8n:
{
"name": "GhostGoogleURLUpdate",
"nodes": [
{
"parameters": {},
"name": "Start",
"type": "n8n-nodes-base.start",
"typeVersion": 1,
"position": [
180,
490
]
},
{
"parameters": {
"authentication": "oAuth2",
"requestMethod": "POST",
"url": "https://indexing.googleapis.com/v3/urlNotifications:publish",
"options": {},
"bodyParametersUi": {
"parameter": [
{
"name": "url",
"value": "={{$node[\"Webhook\"].json[\"body\"][\"post\"][\"current\"][\"url\"]}}"
},
{
"name": "type",
"value": "URL_UPDATED"
}
]
},
"queryParametersUi": {
"parameter": []
}
},
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [
840,
190
],
"credentials": {
"oAuth2Api": "n8n4"
}
},
{
"parameters": {
"httpMethod": "POST",
"path": "",
"options": {}
},
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
550,
190
],
"webhookId": ""
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"id": "1"
}
If you found this in any way helpful :) please comment below I would really appreaciate your input <3
Thanks :)
If you press this Button it will Load Disqus-Comments. More on Disqus Privacy: Link