AMP Start と
Blog の
前提
以下の
OS
CentOS release 6.9 (Final)Python Version
Python 2.7.8Package (必要そうな
ものだけ 抜粋)
Django (1.10.6)
Mezzanine (4.2.3)
参考サイト
AMP Start - Accelarated Mobile Pages Templates
AMP Start テーマの元ネタと して、 Blog Post を 使用しました。 Device Handling — Mezzanine 4.2.3 documentation
Mezzanine のPC モバイル判定の 頁 AMP の
対応方法まとめ
AMP タグを説明してくれている サイト
AMP テーマを 作成しようと 思う 背景
Google の
検索順位が 上がる ことを 期待している。
現状、直接的に 検索順位には 影響しないそうですが、 関節的にはいいかとが あるのではと いう 気持ちが あります。 流行っている
感が ある。
流行っている感が あり、 仕事で 使う 可能性は ないことは なく、
この辺で 一通り 覚えておこうかと いう 気持ちは あります。
テーマ作成の 方針
AMP Start の
Blog Post を なるべく そのままで 作成する。
そのままで いい 感じに 思えましたので、 問題が 発生しない 限りは そのまま 使います。 AMP HTML は、
別 URL に 置くではなく、 同一 URL と して、 Mobile アクセスの 場合、 AMP HTML を 返すようにする。
これは、Mezzanine に Mobile 判定機能が 内蔵されている。
別 URL にした 場合、 Mezzanine の include ファイルが 紐づけられている template タグ類が 使えなくなりそうだった ためです。
同一 URL で切り替えを 行なっても、 Google Search Console で 認識されましたので、
同一 URL で、デバイスに より HTML を 切り替えるでもうまく いくようです。
テーマ作成時に 実施した こと
以下、
Mezzanine の
Mezzanine への 設定追加
Theme を
Tempalte を
Mobile Device の
Theme を
INSTALL_APPS に 追加 settings.py
のINSTALLED_APPS に amp_start_blog_post を 追加しました。 ################ # APPLICATIONS # ################ INSTALLED_APPS = ( .... "mezzanine.twitter", "mezzanine_pubsubhubbub_pub", "mezzanine_extentions", "amp_start_blog_post", ... )
Tempalte を
読み込むための 記載
settings.py
のDIRS に テーマの Template パス os.path.join(BASE_DIR, 'amp_start_blog_post/templates')
を追加しました。 TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': (os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'clean_blog/templates'), os.path.join(BASE_DIR, 'amp_start_blog_post/templates'), os.path.join(BASE_DIR, 'mezzanine_extentions/templates')), 'OPTIONS': {'builtins': ['mezzanine.template.loader_tags'], 'context_processors': (
Mobile Device の
判定の 追加
settings.py
のDEVICE_USER_AGENTS に テーマディレクトリと、
ユーザーエージェントを追加しました。
これで、Mobile ユーザーエージェントの 場合は、 amp_start_blog_post ディレクトリ配下の、
template が使用されるようになります。 ############################# # Device Settings ############################# DEVICE_USER_AGENTS = ( ("amp_start_blog_post", ("Android", "BlackBerry", "iPhone" )), )
補足1. Mobile デバイスの
場合の、 include HTML を 保持する template タグの 動作に ついて
Mezzanine のmenu タグなどは、 include HTML を 保持しています。
include HTML の読み込みには、 @register.inclusion_tag
という デコレータが 使われています。
以下、editable_loader
の実装抜粋です。 この@register.inclusion_tag("includes/editable_loader.html", takes_context=True) def editable_loader(context): """ Set up the required JS/CSS for the in-line editing toolbar and controls. """ user = context["request"].user template_vars = { "has_site_permission": has_site_permission(user), "request": context["request"], } if (settings.INLINE_EDITING_ENABLED and template_vars["has_site_permission"]): t = get_template("includes/editable_toolbar.html") template_vars["REDIRECT_FIELD_NAME"] = REDIRECT_FIELD_NAME template_vars["editable_obj"] = context.get("editable_obj", context.get("page", None)) template_vars["accounts_logout_url"] = context.get( "accounts_logout_url", None) template_vars["toolbar"] = t.render(template_vars) template_vars["richtext_media"] = RichTextField().formfield( ).widget.media return template_vars
@register.inclusion_tag
ですが、mezzanine/init.py at master · stephenmcd/mezzanine · GitHub で 定義されています。 このdef inclusion_tag(self, name, context_class=Context, takes_context=False): """ Replacement for Django's ``inclusion_tag`` which looks up device specific templates at render time. """ def tag_decorator(tag_func): @wraps(tag_func) def tag_wrapper(parser, token): class InclusionTagNode(template.Node): def render(self, context): if not getattr(self, "nodelist", False): try: request = context["request"] except KeyError: t = get_template(name) else: ts = templates_for_device(request, name) t = select_template(ts) self.template = t parts = [template.Variable(part).resolve(context) for part in token.split_contents()[1:]] if takes_context: parts.insert(0, context) result = tag_func(*parts) if context.autoescape: result = conditional_escape(result)fsup return self.template.render(context.flatten()) return InclusionTagNode() return self.tag(tag_wrapper) return tag_decorator
タグですが、 内部で、 templates_for_device
でMoblie か PC かで、 template を 切り替えています。
逆に言うと、 mezzanine の 標準の タグは、 Device Handling
機能を使わないと、 レイアウトの 切り替えが できません。 1
1. モジュールの関数を 書き換えれば 上手く いきそうには 思います。 Pythonに よる 黒魔術入門 補足2. Device Handring 機能が
削除される
Mezzanine の新しいVersionでは、 Device Handring 機能が 削除されるようです。
mezzanine/device-handling.rst at master · stephenmcd/mezzanine
このため、 Device Handring を 使用しない 実装に 書き換えました。
修正した結果は Django で AMP ページ と 通常ページを 振り分ける | Monotalk に 記載しましたので、 そちらもご 確認ください。
Google Tag Manger タグの AMP 対応
amp-analytics
タグで、
記載はbase.html
に
- base.html
{% if settings.AMP_GOOGLE_TAG_MANGER_ID %} <amp-analytics config="https://www.googletagmanager.com/amp.json?id={{settings.AMP_GOOGLE_TAG_MANGER_ID}}>m.url=SOURCE_URL"data-credentials="include"></amp-analytics> {% endif %}
Google analytics タグの AMP 対応
Google Tag Manager 経由で
Template 上に
設定方法は
Google adsense タグの AMP 対応
画面上部、
上部は、fixed-height
、responsive
画面上部 (google_ads_top.html)
{% if settings.AMP_GOOGLE_ADS_CLIENT_ID_TOP and settings.AMP_GOOGLE_ADS_SLOT_ID_TOP %} <section class="{{ section_class }}"> <amp-ad layout="fixed-height" height=100 type="adsense" data-ad-client="{{settings.AMP_GOOGLE_ADS_CLIENT_ID_TOP}}" data-ad-slot="{{settings.AMP_GOOGLE_ADS_SLOT_ID_TOP}}"> </amp-ad> </section> {% endif %}
画面下部 (google_ads_bottom.html)
{% if settings.AMP_GOOGLE_ADS_CLIENT_ID_BOTTOM and settings.AMP_GOOGLE_ADS_SLOT_ID_BOTTOM %} <section class="{{ section_class }}"> <amp-ad layout="responsive" width=300 height=250 type="adsense" data-ad-client="{{settings.AMP_GOOGLE_ADS_CLIENT_ID_BOTTOM}}" data-ad-slot="{{settings.AMP_GOOGLE_ADS_SLOT_ID_BOTTOM}}"> </amp-ad> </section> {% endif %}
Disqus の AMP 対応
以下に
別ドメインに
* AMP の
JSON-LD の 構造化マークアップの 追加
過去に
Mezzanine に
本文HTMLの AMP 対応
本文HTMLの、
現在、
plugin を
filter を
以下、
作成した filter は
* amp_start_blog_post_tags.py
rom __future__ import unicode_literals from mezzanine import template from bs4 import BeautifulSoup from PIL import Image from StringIO import StringIO import requests import json import logging logger = logging.getLogger(__name__) register = template.Library() @register.filter def to_amp_html(html): """ Markdown HTML to AMP HTML """ soup = BeautifulSoup(html, "html5lib") # ------------------------------------------------ # amp id replace to "accelerated-mobile-pages" # ------------------------------------------------ for elem in soup.find_all(True, id=lambda x: x and 'amp' in x): elem["id"] = elem.get("id").replace("amp", "accelerated-mobile-pages") # h2 for h2 in soup.find_all('h2'): h2['class'] = h2.get('class', []) + ['bold', 'mt2', 'mb2'] # h3 for h3 in soup.find_all('h3'): h3['class'] = h3.get('class', []) + ['bold', 'mt1', 'mb1'] # h4 for h4 in soup.find_all('h4'): h4['class'] = h4.get('class', []) + ['bold', 'mt1', 'mb1'] # ------------------------------------------------ # img replace to amp-img # ----------------------------------------------- for img in soup.find_all('img'): try: amp_img = soup.new_tag("amp-img") for attr in img.attrs: if "style" != attr: amp_img[attr] = img[attr] src = str(img.get("src")) if src.startswith("//"): src = src.replace("//", "https://") req = requests.get(src) picture_IO = StringIO(req.content) picture_IO.seek(0) im = Image.open(picture_IO) amp_img["width"] = im.size[0] amp_img["height"] = im.size[1] amp_img["layout"] = "responsive" img.replace_with(amp_img) except IOError: logger.warning("something raised an exception: ", exc_info=True) amp_img["width"] = "4" amp_img["height"] = "3" amp_img["layout"] = "responsive" img.replace_with(amp_img) soup.body.hidden = True return str(soup.body)
説明
BeautifulSoup(html, "html5lib")
は、BeautifulSoup(html)
でも問題なく 動作しますが、 WARNINGが 出力されます。 id に
amp
が指定されている 箇所が あり、 それで 妥当性検証エラーが 発生していたので、 amp
をaccelerated-mobile-pages
に置換する 処理を 追加しました。 h2,h3,h4 タグに
css クラス属性を 付与する 必要が あり、 この タイミングで 実施するようにしました。 Image.open(picture_IO)
で、画像を 取得しwidth、 height を 取得していますが 何故か JPEGの 場合エラーとなり、 エラーの 原因を 解決できなかったため、 乱暴ですが 例外発生時は、 縦横比率 3対4 固定で 設定しています。
PC 向け テンプレート に AMP HTMLへの リンクを 追加
PC 向けの
PC も
<link rel="amphtml" href="{{ request.get_full_path }}">
AMP対応するまでに
に
も
書いてても、
Vary User-Agent の 設定
記事作成後の
動的な
今回のように、
Vary HTTP ヘッダー にVary: User-Agent
を
当ブログだと、
Vary:Cookie,Accept-Language,Accept-Encoding
Order of MIDDLEWARE
をSessionMiddleware は、
Vary:Cookie
を追加する GZipMiddleware は、
Vary:Accept-Encoding
を追加する LocaleMiddleware は、
Vary:Accept-Language
を追加する
という
settings.py で、
Apache の
そちらのVary:Accept-Encoding
が
Vary: User-Agent
の
ドキュメントmod_deflate - Apache HTTP サーバ にも
やり
- mod_deflate.conf
# Make sure proxies don't deliver the wrong content Header append Vary User-Agent env=!dont-vary
作成した テーマ一式
Github に
kemsakurai/mezzanine-theme-amp-start-blog-post: mezzanine theme based by amp start
以上です。
過去に、
mezzanineの
コメント