.htaccess для ботов SEO, сканирующих одностраничные приложения без hashbangs

Используя страницу pushState enabled, как правило, вы перенаправляете SEO-боты, используя соглашение escaped_fragment. Вы можете узнать больше об этом здесь.

В соглашении предполагается, что вы будете использовать префикс hashbang (#!) перед всем вашим URI на одностраничном приложении. SEO-боты будут избегать этих фрагментов, заменив хэш-банд своим собственным узнаваемым соглашением escaped_fragment при создании запроса страницы.

//Your page
http://example.com/#!home

//Requested by bots as
http://example.com/?_escaped_fragment=home

Это позволяет администратору сайта обнаруживать боты и перенаправлять их на кэшированную предварительно записанную страницу.

RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule ^(.*)$  https://s3.amazonaws.com/mybucket/$1 [P,QSA,L]

Проблема заключается в том, что хеш-бэнг быстро прекращается с помощью широко адаптированной поддержки pushState. Это также очень уродливо и не очень интуитивно понятно для пользователя.

Итак, что, если мы использовали режим HTML5, где pushState направляет все пользовательское приложение?

//Your index is using pushState
http://example.com/

//Your category is using pushState (not a folder)
http://example.com/category

//Your category/subcategory is using pushState
http://example.com/category/subcategory

Можно ли переписать правила для ботов в вашу кеш-версию, используя это новое соглашение? Связанные, но только учетные записи для края индекса. Google также имеет статью, который предлагает использовать метод opt-in для этого случая с одним краем, используя <meta name="fragment" content="!"> в <head> страницы. Опять же, это для одного края. Здесь мы говорим о том, как обрабатывать каждую страницу в качестве сменного входа.

http://example.com/?escaped_fragment=
http://example.com/category?escaped_fragment=
http://example.com/category/subcategory?escaped_fragment=

Я думаю, что escaped_fragment все еще можно использовать как идентификатор для ботов SEO, и что я мог бы извлечь все, что находится между доменом и этим идентификатором, чтобы добавить в мое местоположение в ковше, например:

RewriteCond %{QUERY_STRING} ^_escaped_fragment_=$
# (high level example I have no idea how to do this)
# extract "category/subcategory" == $2
# from http://example.com/category/subcategory?escaped_fragment=
RewriteRule ^(.*)$  https://s3.amazonaws.com/mybucket/$2 [P,QSA,L]

Какой лучший способ справиться с этим?

Ответ 1

У вас была аналогичная проблема в одностраничном веб-приложении.

Единственное решение, которое я нашел для этой проблемы, - это эффективное создание статических версий страниц с целью создания чего-то навигационного с помощью Google (и других) ботов.

Вы можете сделать это самостоятельно, но есть также службы, которые выполняют именно это, и создают для вас свой статический кеш (и служат для моментальных снимков для ботов по их CDN).

В итоге я использовал SEO4Ajax, хотя доступны другие подобные услуги!

Ответ 2

У меня была такая же проблема. На данный момент я изменил .htaccess следующим образом:

RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule ^$ /snapshots/index.html? [L,NC]
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule ^(.*)$ /snapshots/$1.html? [L,NC]

Не уверен, есть ли лучшее решение, но оно работает для меня до сих пор. Просто убедитесь, что структура каталогов для ваших снимков соответствует структуре URL.

Ответ 3

Я использую Symfony2, и хотя мне говорят другие разработчики, что Googlebot и Bingbot работают с Javascript достаточно хорошо, чтобы генерировать собственные HTML-фрагменты, я не уверен в себе. Я также считаю, что обслуживание статических ресурсов - лучшая альтернатива для работы ppl с отключенным JS (хотя это маловероятно), и поэтому я заинтересован в обслуживании HTML-фрагментов в любом случае, если это не хлопот. Ниже приведен метод, который я собираюсь использовать, но не пробовал:

Вот другие вопросы SO, которые похожи (один мой).
Angularjs против SEO против pushState
HTML-фрагменты для приложения AngularJS, использующего pushState?

Вот решение, которое я разместил в этом вопросе и рассматриваю для себя в случае, если я хочу отправить фрагменты HTML в боты. Это было бы решением для бэкэнд Symfony2:

  • Используйте prerender или другую службу для создания статических фрагментов всех ваших страниц. Храните их в любом месте, доступном вашему маршрутизатору.
  • В вашем файле маршрутизации Symfony2 создайте маршрут, соответствующий вашему SPA. У меня есть тестовый SPA, работающий на localhost.com/ng-test/, поэтому мой маршрут будет выглядеть следующим образом:

    # Adding a trailing / to this route breaks it. Not sure why.
    # This is also not formatting correctly in StackOverflow. This is yaml.
    NgTestReroute:
    ----path: /ng-test/{one}/{two}/{three}/{four}
    ----defaults:
    --------_controller: DriverSideSiteBundle:NgTest:ngTestReroute
    --------'one': null
    --------'two': null
    --------'three': null
    --------'four': null
    ----methods: [GET]

  • В вашем контроллере Symfony2 проверьте пользовательский агент, чтобы узнать, является ли он googlebot или bingbot. Вы должны сделать это с помощью кода ниже, а затем использовать этот список для целевых ботов, которые вас интересуют (http://www.searchenginedictionary.com/spider-names.shtml)...

    if(strstr(strtolower($_SERVER['HTTP_USER_AGENT']), "googlebot"))
    {
      // what to do
    }

  • Если ваш контроллер обнаружит совпадение с ботом, отправьте ему фрагмент HTML. В противном случае, как и в случае с моим приложением AngularJS, просто отправьте пользователя на индексную страницу, а Angular будет делать все остальное.

Кроме того, если на ваш вопрос был дан ответ, выберите его, чтобы я и другие могли рассказать, что сработало для вас.

Ответ 4

Я использую PhantomJS для создания статических снимков моих страниц. Моя структура каталогов только на одном уровне (root и /projects), поэтому у меня есть два файла .htaccess, в которых я перенаправляюсь к файлу PHP (index-bots.php), который запускает процесс PhantomJS, указанный в моем SPA index.html и выводит отображаемые статические страницы.

Файлы .htaccess выглядят следующим образом:

/. Htaccess

# redirect search engine bots to index-bots.php
# in order to serve rendered HTML via phantomjs
RewriteCond %{HTTP_USER_AGENT} (bot|crawl|slurp|spider) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/index-bots\.php [NC]
RewriteRule ^(.*)$ index-bots.php?url=%{REQUEST_URI} [L,QSA]

/projects/.htaccess

# redirect search engine bots to index-bots.php
# in order to serve rendered HTML via phantomjs
RewriteCond %{HTTP_USER_AGENT} (bot|crawl|slurp|spider) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ ../index-bots.php?url=%{REQUEST_URI} [L,QSA]

Несколько примечаний:

  • !-f RewriteCond имеет решающее значение! Поскольку .htaccess будет применять RewriteRule ко всем запросам, ресурсы на вашей странице будут переписаны в файл PHP, развернув несколько экземпляров PhantomJS и доведя ваш сервер до колен.
  • Также важно освободить index-bots.php от перезаписи, чтобы избежать бесконечного цикла.
  • Я выделяю JS в своем бегуне PhantomJS script, чтобы гарантировать, что JS ничего не делает, когда боты, которые его поддерживают, сталкиваются с "статическими" страницами.
  • Я не мастер .htaccess, поэтому, вероятно, лучший способ сделать это. Я бы хотел услышать это, если да.