动态内容单页应用SEO
Dynamic content Single Page Application SEO
我是 SEO 的新手,只是想了解它如何为具有动态内容的单页应用程序工作。
就我而言,我有一个单页应用程序(由 AngularJS 提供支持,使用路由器显示不同的状态)提供了一些 location-based 搜索功能,类似于 Zillow, Redfin, or Yelp。在 mt 站点上,用户可以输入位置名称,该站点将 return 一些基于该位置的结果。
我正在尝试找出一种方法使其与 Google 配合良好。例如,如果我在 Google 中输入 "Apartment San Francisco",结果将是:
当用户点击这些链接时,网站将显示正确的结果。我正在考虑为我的网站提供类似的 SEO。
问题是,页面内容完全取决于用户的查询。用户可以通过城市名称、州名称、邮政编码等进行搜索,以显示不同的结果,并且不可能将它们都放入站点地图中。 google 如何抓取此类动态页面结果的内容?
我没有 SEO 经验,也不确定如何为我的网站做这件事。请分享一些经验或建议以帮助我入门。非常感谢!
===========
跟进问题:
我看到 Googlebot 可以 now run Javascript。我想更多地了解这一点。
当我的 SPA 应用程序的特定 url 打开时,它会进行一些网络查询(XHR 请求)几秒钟,然后显示页面内容。在这种情况下,GoogleBot 会等待 http 响应吗?
我看到一些教程说我们需要专门为搜索引擎准备静态 html。如果我只想处理 Google,是否意味着我不必再提供静态 html 因为 Google 可以 运行 Javascript?
再次感谢。
如果搜索引擎应该访问您的 JavaScript 应用程序,那么我们有权将搜索引擎重定向到另一个 URL 提供完全呈现的页面版本。
为了这份工作
- 您可以使用 Thomas Davis 在 github
上提供的这个工具
或
- 您可以使用下面的代码来完成与上面相同的工作此代码也可用 here
使用Phantom.js
实现
我们可以设置一个 node.js 服务器,给定 URL,它将完全呈现页面内容。然后我们会将机器人重定向到此服务器以检索正确的内容。
我们需要将 node.js 和 phantom.js 安装到一个盒子上。然后在下面启动这个服务器。有两个文件,一个是web服务器,另一个是渲染页面的phantomjs脚本。
// web.js
// Express is our web server that can handle request
var express = require('express');
var app = express();
var getContent = function(url, callback) {
var content = '';
// Here we spawn a phantom.js process, the first element of the
// array is our phantomjs script and the second element is our url
var phantom = require('child_process').spawn('phantomjs',['phantom-server.js', url]);
phantom.stdout.setEncoding('utf8');
// Our phantom.js script is simply logging the output and
// we access it here through stdout
phantom.stdout.on('data', function(data) {
content += data.toString();
});
phantom.on('exit', function(code) {
if (code !== 0) {
console.log('We have an error');
} else {
// once our phantom.js script exits, let's call out call back
// which outputs the contents to the page
callback(content);
}
});
};
var respond = function (req, res) {
// Because we use [P] in htaccess we have access to this header
url = 'http://' + req.headers['x-forwarded-host'] + req.params[0];
getContent(url, function (content) {
res.send(content);
});
}
app.get(/(.*)/, respond);
app.listen(3000);
下面的脚本是phantom-server.js,将负责完整渲染内容。在页面完全呈现之前,我们不会 return 内容。我们挂接到资源侦听器来执行此操作。
var page = require('webpage').create();
var system = require('system');
var lastReceived = new Date().getTime();
var requestCount = 0;
var responseCount = 0;
var requestIds = [];
var startTime = new Date().getTime();
page.onResourceReceived = function (response) {
if(requestIds.indexOf(response.id) !== -1) {
lastReceived = new Date().getTime();
responseCount++;
requestIds[requestIds.indexOf(response.id)] = null;
}
};
page.onResourceRequested = function (request) {
if(requestIds.indexOf(request.id) === -1) {
requestIds.push(request.id);
requestCount++;
}
};
// Open the page
page.open(system.args[1], function () {});
var checkComplete = function () {
// We don't allow it to take longer than 5 seconds but
// don't return until all requests are finished
if((new Date().getTime() - lastReceived > 300 && requestCount === responseCount) || new Date().getTime() - startTime > 5000) {
clearInterval(checkCompleteInterval);
console.log(page.content);
phantom.exit();
}
}
// Let us check to see if the page is finished rendering
var checkCompleteInterval = setInterval(checkComplete, 1);
一旦我们启动了该服务器,运行 我们只需将机器人重定向到客户端 Web 服务器配置中的服务器。
重定向机器人
如果您使用的是 apache,我们可以编辑掉 .htaccess,以便 Google 请求被代理到我们的中间人 phantom.js 服务器。
RewriteEngine on
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule (.*) http://webserver:3000/%1? [P]
我们还可以包含其他 RewriteCond
,例如用于重定向我们希望编入索引的其他搜索引擎的用户代理。
尽管 Google 不会使用 _escaped_fragment_
除非我们通过包含元标记来告诉它; <meta name="fragment" content="!">
或在我们的链接中使用 #!
URL。
您很可能必须同时使用两者。
已使用 Google 网站管理员抓取工具对此进行了测试。使用抓取工具时,确保在 URL 中包含 #!
。
我是 SEO 的新手,只是想了解它如何为具有动态内容的单页应用程序工作。
就我而言,我有一个单页应用程序(由 AngularJS 提供支持,使用路由器显示不同的状态)提供了一些 location-based 搜索功能,类似于 Zillow, Redfin, or Yelp。在 mt 站点上,用户可以输入位置名称,该站点将 return 一些基于该位置的结果。
我正在尝试找出一种方法使其与 Google 配合良好。例如,如果我在 Google 中输入 "Apartment San Francisco",结果将是:
当用户点击这些链接时,网站将显示正确的结果。我正在考虑为我的网站提供类似的 SEO。
问题是,页面内容完全取决于用户的查询。用户可以通过城市名称、州名称、邮政编码等进行搜索,以显示不同的结果,并且不可能将它们都放入站点地图中。 google 如何抓取此类动态页面结果的内容?
我没有 SEO 经验,也不确定如何为我的网站做这件事。请分享一些经验或建议以帮助我入门。非常感谢!
===========
跟进问题:
我看到 Googlebot 可以 now run Javascript。我想更多地了解这一点。
当我的 SPA 应用程序的特定 url 打开时,它会进行一些网络查询(XHR 请求)几秒钟,然后显示页面内容。在这种情况下,GoogleBot 会等待 http 响应吗?
我看到一些教程说我们需要专门为搜索引擎准备静态 html。如果我只想处理 Google,是否意味着我不必再提供静态 html 因为 Google 可以 运行 Javascript?
再次感谢。
如果搜索引擎应该访问您的 JavaScript 应用程序,那么我们有权将搜索引擎重定向到另一个 URL 提供完全呈现的页面版本。
为了这份工作
- 您可以使用 Thomas Davis 在 github 上提供的这个工具
或
- 您可以使用下面的代码来完成与上面相同的工作此代码也可用 here
使用Phantom.js
实现我们可以设置一个 node.js 服务器,给定 URL,它将完全呈现页面内容。然后我们会将机器人重定向到此服务器以检索正确的内容。
我们需要将 node.js 和 phantom.js 安装到一个盒子上。然后在下面启动这个服务器。有两个文件,一个是web服务器,另一个是渲染页面的phantomjs脚本。
// web.js
// Express is our web server that can handle request
var express = require('express');
var app = express();
var getContent = function(url, callback) {
var content = '';
// Here we spawn a phantom.js process, the first element of the
// array is our phantomjs script and the second element is our url
var phantom = require('child_process').spawn('phantomjs',['phantom-server.js', url]);
phantom.stdout.setEncoding('utf8');
// Our phantom.js script is simply logging the output and
// we access it here through stdout
phantom.stdout.on('data', function(data) {
content += data.toString();
});
phantom.on('exit', function(code) {
if (code !== 0) {
console.log('We have an error');
} else {
// once our phantom.js script exits, let's call out call back
// which outputs the contents to the page
callback(content);
}
});
};
var respond = function (req, res) {
// Because we use [P] in htaccess we have access to this header
url = 'http://' + req.headers['x-forwarded-host'] + req.params[0];
getContent(url, function (content) {
res.send(content);
});
}
app.get(/(.*)/, respond);
app.listen(3000);
下面的脚本是phantom-server.js,将负责完整渲染内容。在页面完全呈现之前,我们不会 return 内容。我们挂接到资源侦听器来执行此操作。
var page = require('webpage').create();
var system = require('system');
var lastReceived = new Date().getTime();
var requestCount = 0;
var responseCount = 0;
var requestIds = [];
var startTime = new Date().getTime();
page.onResourceReceived = function (response) {
if(requestIds.indexOf(response.id) !== -1) {
lastReceived = new Date().getTime();
responseCount++;
requestIds[requestIds.indexOf(response.id)] = null;
}
};
page.onResourceRequested = function (request) {
if(requestIds.indexOf(request.id) === -1) {
requestIds.push(request.id);
requestCount++;
}
};
// Open the page
page.open(system.args[1], function () {});
var checkComplete = function () {
// We don't allow it to take longer than 5 seconds but
// don't return until all requests are finished
if((new Date().getTime() - lastReceived > 300 && requestCount === responseCount) || new Date().getTime() - startTime > 5000) {
clearInterval(checkCompleteInterval);
console.log(page.content);
phantom.exit();
}
}
// Let us check to see if the page is finished rendering
var checkCompleteInterval = setInterval(checkComplete, 1);
一旦我们启动了该服务器,运行 我们只需将机器人重定向到客户端 Web 服务器配置中的服务器。
重定向机器人 如果您使用的是 apache,我们可以编辑掉 .htaccess,以便 Google 请求被代理到我们的中间人 phantom.js 服务器。
RewriteEngine on
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule (.*) http://webserver:3000/%1? [P]
我们还可以包含其他 RewriteCond
,例如用于重定向我们希望编入索引的其他搜索引擎的用户代理。
尽管 Google 不会使用 _escaped_fragment_
除非我们通过包含元标记来告诉它; <meta name="fragment" content="!">
或在我们的链接中使用 #!
URL。
您很可能必须同时使用两者。
已使用 Google 网站管理员抓取工具对此进行了测试。使用抓取工具时,确保在 URL 中包含 #!
。