Skip to content

Commit 939d07f

Browse files
authored
Merge pull request #17 from umbraco/feature/google-search-console
Feature/google search console
2 parents 5f90b67 + 6208554 commit 939d07f

23 files changed

+1009
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.w25r { width: 25rem;}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
function urlInspectionToolController(editorState, notificationsService, umbracoCmsIntegrationsGoogleSearchConsoleUrlInspectionToolResource) {
2+
var vm = this;
3+
4+
vm.loading = false;
5+
vm.showResults = false;
6+
vm.oauthConfiguration = {};
7+
vm.inspectionResult = {};
8+
9+
// build default url inspection object
10+
var nodeUrls = getUrls();
11+
vm.inspectionObj = {
12+
urls: nodeUrls,
13+
inspectionUrl: nodeUrls[0],
14+
siteUrl: window.location.origin,
15+
languageCode: editorState.current.urls[0].culture,
16+
multipleUrls: editorState.current.urls.length > 1,
17+
enabled: false
18+
};
19+
20+
// get oauth configuration
21+
umbracoCmsIntegrationsGoogleSearchConsoleUrlInspectionToolResource.getOAuthConfiguration().then(function (response) {
22+
vm.oauthConfiguration = response;
23+
});
24+
25+
vm.onConnectClick = function () {
26+
vm.authorizationWindow = window.open(vm.oauthConfiguration.authorizationUrl,
27+
"GoogleSearchConsole_Authorize",
28+
"width=900,height=700,modal=yes,alwaysRaised=yes");
29+
}
30+
31+
vm.onRevokeToken = function () {
32+
revokeToken();
33+
}
34+
35+
vm.onInspect = function () {
36+
37+
vm.loading = true;
38+
39+
// check if url is relative
40+
if (isRelativeUrl(vm.inspectionObj.inspectionUrl))
41+
vm.inspectionObj.inspectionUrl = `${vm.inspectionObj.siteUrl}${vm.inspectionObj.inspectionUrl}`;
42+
43+
umbracoCmsIntegrationsGoogleSearchConsoleUrlInspectionToolResource.inspect(vm.inspectionObj.inspectionUrl, vm.inspectionObj.siteUrl, vm.inspectionObj.languageCode)
44+
.then(function (response) {
45+
46+
vm.loading = false;
47+
48+
if (response.error !== undefined && response.error !== null) {
49+
50+
notificationsService.warning(response.error.status, response.error.message);
51+
52+
// if token expired -> refresh access token
53+
if (response.error.code === "401") {
54+
vm.isConnected = false;
55+
56+
// refresh access token
57+
refreshAccessToken();
58+
}
59+
} else {
60+
vm.showResults = true;
61+
vm.inspectionResult = response.inspectionResult;
62+
}
63+
});
64+
}
65+
66+
vm.onEdit = function () {
67+
vm.inspectionObj.multipleUrls = false;
68+
vm.inspectionObj.enabled = true;
69+
}
70+
71+
vm.onChangeInspectionUrl = function () {
72+
vm.inspectionObj.languageCode =
73+
editorState.current.urls.find(p => p.text === vm.inspectionObj.inspectionUrl).culture;
74+
}
75+
76+
// authorization listener
77+
window.addEventListener("message", function (event) {
78+
if (event.data.type === "google:oauth:success") {
79+
80+
var codeParam = "?code=";
81+
var scopeParam = "&scope=";
82+
83+
vm.authorizationWindow.close();
84+
85+
var code = event.data.url.slice(event.data.url.indexOf(codeParam) + codeParam.length, event.data.url.indexOf(scopeParam));
86+
87+
umbracoCmsIntegrationsGoogleSearchConsoleUrlInspectionToolResource.getAccessToken(code).then(function (response) {
88+
if (response !== "error") {
89+
vm.oauthConfiguration.isConnected = true;
90+
notificationsService.success("Google Search Console Authorization", "Access Approved");
91+
} else {
92+
notificationsService.error("Google Search Console Authorization", "Access Denied");
93+
}
94+
});
95+
} else if (event.data.type === "google:oauth:denied") {
96+
notificationsService.error("Google Search Console Authorization", "Access Denied");
97+
vm.oauthConfiguration.isConnected = false;
98+
vm.authorizationWindow.close();
99+
}
100+
101+
}, false);
102+
103+
function refreshAccessToken() {
104+
notificationsService.warning("Google Search Console Authorization", "Refreshing access token.");
105+
106+
umbracoCmsIntegrationsGoogleSearchConsoleUrlInspectionToolResource.refreshAccessToken().then(
107+
function (response) {
108+
if (response.length !== "error") {
109+
110+
notificationsService.success("Google Search Console Authorization",
111+
"Refresh access token - completed.");
112+
113+
vm.isConnected = true;
114+
} else
115+
notificationsService.error("Google Search Console Authorization",
116+
"An error has occurred.");
117+
});
118+
}
119+
120+
function revokeToken() {
121+
umbracoCmsIntegrationsGoogleSearchConsoleUrlInspectionToolResource.revokeToken().then(function () {
122+
vm.oauthConfiguration.isConnected = false;
123+
vm.showResults = false;
124+
});
125+
}
126+
127+
function isRelativeUrl(url) {
128+
var regExp = new RegExp('^(?:[a-z]+:)?//', 'i');
129+
return !regExp.test(url);
130+
}
131+
132+
function getUrls() {
133+
var arr = [];
134+
135+
for (var i = 0; i < editorState.current.urls.length; i++) {
136+
var url = isRelativeUrl(editorState.current.urls[i].text)
137+
? `${window.location.origin}${editorState.current.urls[i].text}`
138+
: editorState.current.urls[i].text;
139+
140+
if (arr.indexOf(url) === -1) {
141+
arr.push(url);
142+
}
143+
}
144+
145+
return arr;
146+
}
147+
}
148+
149+
angular.module("umbraco")
150+
.controller("UmbracoCms.Integrations.GoogleSearchConsole.UrlInspectionToolController", urlInspectionToolController)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
function urlInspectionToolResource($http, umbRequestHelper) {
2+
3+
const apiEndpoint = "backoffice/UmbracoCmsIntegrationsGoogleSearchConsole/UrlInspectionApi";
4+
5+
return {
6+
getOAuthConfiguration: function () {
7+
return umbRequestHelper.resourcePromise(
8+
$http.get(`${apiEndpoint}/GetOAuthConfiguration`),
9+
"Failed to retrieve resource");
10+
},
11+
getAccessToken: function (authorizationCode) {
12+
return umbRequestHelper.resourcePromise(
13+
$http.post(`${apiEndpoint}/GetAccessToken`, { code: authorizationCode }), "Failed to retrieve resource");
14+
},
15+
refreshAccessToken: function () {
16+
return umbRequestHelper.resourcePromise(
17+
$http.post(`${apiEndpoint}/RefreshAccessToken`), "Failed to retrieve resource");
18+
},
19+
revokeToken: function () {
20+
return umbRequestHelper.resourcePromise(
21+
$http.post(`${apiEndpoint}/RevokeToken`), "Failed to retrieve resource");
22+
},
23+
inspect: function (inspectionUrl, siteUrl, languageCode) {
24+
return umbRequestHelper.resourcePromise(
25+
$http.post(`${apiEndpoint}/Inspect`, { inspectionUrl: inspectionUrl, siteUrl: siteUrl, languageCode: languageCode }), "Failed to retrieve resource");
26+
}
27+
};
28+
}
29+
30+
angular.module("umbraco.resources")
31+
.factory("umbracoCmsIntegrationsGoogleSearchConsoleUrlInspectionToolResource", urlInspectionToolResource);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<language>
3+
<area alias="urlInspectionTool">
4+
<key alias="title">URL Inspection Tool</key>
5+
</area>
6+
</language>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"javascript": [
3+
"~/App_Plugins/UmbracoCms.Integrations/SEO/GoogleSearchConsole/URLInspectionTool/js/url-inspection-tool.resource.js",
4+
"~/App_Plugins/UmbracoCms.Integrations/SEO/GoogleSearchConsole/URLInspectionTool/js/url-inspection-tool.controller.js"
5+
],
6+
"css": [
7+
"~/App_Plugins/UmbracoCms.Integrations/SEO/GoogleSearchConsole/URLInspectionTool/css/urlInspection.css"
8+
]
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<div ng-controller="UmbracoCms.Integrations.GoogleSearchConsole.UrlInspectionToolController as vm">
2+
<umb-load-indicator ng-if="vm.loading"></umb-load-indicator>
3+
<umb-box>
4+
<umb-box-header title-key="urlInspectionTool_title">
5+
<umb-button action="vm.onConnectClick()"
6+
type="button"
7+
button-style="primary"
8+
state="init"
9+
label="Connect"
10+
disabled="vm.oauthConfiguration.isConnected">
11+
</umb-button>
12+
<umb-button action="vm.onRevokeToken()"
13+
type="button"
14+
button-style="danger"
15+
state="init"
16+
label="Revoke"
17+
disabled="!vm.oauthConfiguration.isConnected">
18+
</umb-button>
19+
</umb-box-header>
20+
<umb-box-content>
21+
<div>
22+
<h5>About Google Search Console - URL Inspection API</h5>
23+
<p>
24+
The Search Console APIs are a way to access data outside of Search Console, through external applications and products.
25+
</p>
26+
<p>
27+
You can request the data Search Console has about the indexed version of the current node, and the API will return the indexed information.
28+
</p>
29+
<p>
30+
The request parameters include the URL you'd like to inspect and the URL of the property as defined in Search Console.
31+
</p>
32+
<p>
33+
The response includes analysis results containing information from Search Console, including index status, AMP, rich results and mobile usability.
34+
</p>
35+
<p>
36+
Usage limits - the quote is enforced per Search Console website property: 2000 queries per day / 600 queries per minute.
37+
</p>
38+
</div>
39+
<div class="flex justify-start">
40+
<div class="flx-b2">
41+
<div class="flex justify-start">
42+
<div class="w25r">
43+
<h5>Inspection URL</h5>
44+
<input type="text" class="w-100" ng-if="!vm.inspectionObj.multipleUrls" ng-model="vm.inspectionObj.inspectionUrl"
45+
no-dirty-check ng-disabled="!vm.inspectionObj.enabled" />
46+
<select ng-if="vm.inspectionObj.multipleUrls" ng-model="vm.inspectionObj.inspectionUrl" ng-change="vm.onChangeInspectionUrl()"
47+
no-dirty-check class="w-100">
48+
<option ng-repeat="url in vm.inspectionObj.urls" value="{{ url }}">{{ url }}</option>
49+
</select>
50+
</div>
51+
<div class="ml3 w25r">
52+
<h5>Site URL</h5>
53+
<input type="text" class="w-100" ng-model="vm.inspectionObj.siteUrl" no-dirty-check ng-disabled="!vm.inspectionObj.enabled"/>
54+
</div>
55+
</div>
56+
</div>
57+
</div>
58+
<div class="flex justify-start">
59+
<div class="flx-b2">
60+
<div class="flex justify-start">
61+
<div>
62+
<umb-button action="vm.onInspect()"
63+
type="button"
64+
button-style="primary"
65+
state="init"
66+
label="Inspect"
67+
disabled="!vm.oauthConfiguration.isConnected">
68+
</umb-button>
69+
</div>
70+
<div>
71+
<umb-button action="vm.onEdit()"
72+
type="button"
73+
button-style="warning"
74+
state="init"
75+
label="Edit"
76+
disabled="!vm.oauthConfiguration.isConnected">
77+
</umb-button>
78+
</div>
79+
</div>
80+
</div>
81+
</div>
82+
<div class="mt4" ng-if="vm.showResults">
83+
<umb-box>
84+
<umb-box-header title="Inspection Result Link" description="Link to Search Console URL inspection."></umb-box-header>
85+
<umb-box-content>
86+
<a href="{{ vm.inspectionResult.inspectionResultLink }}">{{ vm.inspectionResult.inspectionResultLink }}</a>
87+
</umb-box-content>
88+
</umb-box>
89+
<umb-box ng-if="vm.inspectionResult.indexStatusResult">
90+
<umb-box-header title="Index Status Result" description="Result of the index status analysis."></umb-box-header>
91+
<umb-box-content>
92+
<p ng-repeat="(key, value) in vm.inspectionResult.indexStatusResult">
93+
<b>{{key}}</b> {{ value }}
94+
</p>
95+
</umb-box-content>
96+
</umb-box>
97+
<umb-box ng-if="vm.inspectionResult.ampResult">
98+
<umb-box-header title="AMP Result" description="Result of the AMP analysis. Absent if the page is not an AMP page."></umb-box-header>
99+
<umb-box-content>
100+
<p ng-repeat="(key, value) in vm.inspectionResult.ampResult">
101+
<b>{{key}}</b> {{ value }}
102+
</p>
103+
</umb-box-content>
104+
</umb-box>
105+
<umb-box ng-if="vm.inspectionResult.mobileUsabilityResult">
106+
<umb-box-header title="Mobile Usability Result" description="Result of the Mobile usability analysis."></umb-box-header>
107+
<umb-box-content>
108+
<p ng-repeat="(key, value) in vm.inspectionResult.mobileUsabilityResult">
109+
<b>{{key}}</b> {{ value }}
110+
</p>
111+
</umb-box-content>
112+
</umb-box>
113+
<umb-box ng-if="vm.inspectionResult.richResultsResult">
114+
<umb-box-header title="Rich Results Result" description="Result of the Rich Results analysis. Absent if there are no rich results found."></umb-box-header>
115+
<umb-box-content>
116+
<p ng-repeat="(key, value) in vm.inspectionResult.richResultsResult">
117+
<b>{{key}}</b> {{ value }}
118+
</p>
119+
</umb-box-content>
120+
</umb-box>
121+
</div>
122+
</umb-box-content>
123+
</umb-box>
124+
</div>

0 commit comments

Comments
 (0)