Skip to content

Commit

Permalink
Merge pull request #77 from okazy/feature/seo-product-detail
Browse files Browse the repository at this point in the history
Feature/seo product detail
  • Loading branch information
okazy authored Apr 5, 2021
2 parents 0775834 + b0f8d15 commit ad660fe
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 24 deletions.
10 changes: 1 addition & 9 deletions src/Eccube/Resource/doctrine/import_csv/en/dtb_page.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ id,page_name,url,file_name,edit_type,author,description,keyword,create_date,upda
0,Preview,preview,,1,,,,2017-03-07 10:14:52,2017-03-07 10:14:52,,,page,
1,Home,homepage,index,2,,,,2017-03-07 10:14:52,2017-03-07 10:14:52,,,page,
2,All Products,product_list,Product/list,2,,,,2017-03-07 10:14:52,2017-03-07 10:14:52,,,page,
3,Product Details,product_detail,Product/detail,2,,,,2017-03-07 10:14:52,2017-03-07 10:14:52,,,page,"<meta property=""og:type"" content=""og:product"" />
<meta property=""og:title"" content=""{{ Product.name }}"" />
<meta property=""og:image"" content=""{{ url('homepage') }}{{ asset(Product.main_list_image|no_image_product, 'save_image') }}"" />
<meta property=""og:description"" content=""{{ Product.description_list|striptags }}"" />
<meta property=""og:url"" content=""{{ url('product_detail', {'id': Product.id}) }}"" />
<meta property=""product:price:amount"" content=""{{ Product.getPrice02IncTaxMin }}""/>
<meta property=""product:price:currency"" content=""{{ eccube_config.currency }}""/>
<meta property=""product:product_link"" content=""{{ url('product_detail', {'id': Product.id}) }}""/>
<meta property=""product:retailer_title"" content=""{{ BaseInfo.shop_name }}""/>"
3,Product Details,product_detail,Product/detail,2,,,,2017-03-07 10:14:52,2017-03-07 10:14:52,,,page,
4,My Account,mypage,Mypage/index,2,,,,2017-03-07 10:14:52,2017-03-07 10:14:52,noindex,,page,
5,My Account / Edit Customer Info (Form),mypage_change,Mypage/change,2,,,,2017-03-07 10:14:52,2017-03-07 10:14:52,noindex,,page,
6,My Account / Edit Customer Info (Thank-you),mypage_change_complete,Mypage/change_complete,2,,,,2017-03-07 10:14:52,2017-03-07 10:14:52,noindex,,page,
Expand Down
10 changes: 1 addition & 9 deletions src/Eccube/Resource/doctrine/import_csv/ja/dtb_page.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ id,page_name,url,file_name,edit_type,author,description,keyword,create_date,upda
"0","プレビューデータ","preview",,"1",,,,"2017-03-07 10:14:52","2017-03-07 10:14:52",,,"page",
"1","TOPページ","homepage","index","2",,,,"2017-03-07 10:14:52","2017-03-07 10:14:52",,,"page",
"2","商品一覧ページ","product_list","Product/list","2",,,,"2017-03-07 10:14:52","2017-03-07 10:14:52",,,"page",
"3","商品詳細ページ","product_detail","Product/detail","2",,,,"2017-03-07 10:14:52","2017-03-07 10:14:52",,,"page","<meta property=""og:type"" content=""og:product"" />
<meta property=""og:title"" content=""{{ Product.name }}"" />
<meta property=""og:image"" content=""{{ url('homepage') }}{{ asset(Product.main_list_image|no_image_product, 'save_image') }}"" />
<meta property=""og:description"" content=""{{ Product.description_list|striptags }}"" />
<meta property=""og:url"" content=""{{ url('product_detail', {'id': Product.id}) }}"" />
<meta property=""product:price:amount"" content=""{{ Product.getPrice02IncTaxMin }}""/>
<meta property=""product:price:currency"" content=""{{ eccube_config.currency }}""/>
<meta property=""product:product_link"" content=""{{ url('product_detail', {'id': Product.id}) }}""/>
<meta property=""product:retailer_title"" content=""{{ BaseInfo.shop_name }}""/>"
"3","商品詳細ページ","product_detail","Product/detail","2",,,,"2017-03-07 10:14:52","2017-03-07 10:14:52",,,"page",
"4","MYページ","mypage","Mypage/index","2",,,,"2017-03-07 10:14:52","2017-03-07 10:14:52","noindex",,"page",
"5","MYページ/会員登録内容変更(入力ページ)","mypage_change","Mypage/change","2",,,,"2017-03-07 10:14:52","2017-03-07 10:14:52","noindex",,"page",
"6","MYページ/会員登録内容変更(完了ページ)","mypage_change_complete","Mypage/change_complete","2",,,,"2017-03-07 10:14:52","2017-03-07 10:14:52","noindex",,"page",
Expand Down
3 changes: 2 additions & 1 deletion src/Eccube/Resource/locale/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,7 @@ admin.content.page_meta_description: description
admin.content.page_meta_keyword: keyword
admin.content.page_meta_robot: robot
admin.content.page_meta_metatag: metatag
# Deprecated https://github.com/EC-CUBE/ec-cube/pull/4987
admin.content.page_meta_metatag_placeholder: |
商品詳細ページでの記載例
<meta property="og:type" content="og:product" />
Expand Down Expand Up @@ -1596,7 +1597,7 @@ tooltip.content.page_file_name: This is the name of a twig template file which h
tooltip.content.page_source_code: Editing the template file. Coding has to be with twig.
tooltip.content.page_layout: Selecting the layouts to be applied to this page.
tooltip.content.page_meta: You can enter the META tag contents of the page.
tooltip.content.page_meta_tags: You can add META tag freely. You can also use variables used within twig.
tooltip.content.page_meta_tags: You can modify META tags freely. You can also use variables used within twig. If unspecified, meta.twig file in the template folder will be loaded.
tooltip.content.js_source_code: Editing the JavaScript file. Coding has to be with JavaScript.
tooltip.content.css_source_code: Editing the CSS file. Coding has to be with CSS.
tooltip.content.block_name: This is a name of a block for management use.
Expand Down
3 changes: 2 additions & 1 deletion src/Eccube/Resource/locale/messages.ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,7 @@ admin.content.page_meta_description: description
admin.content.page_meta_keyword: keyword
admin.content.page_meta_robot: robot
admin.content.page_meta_metatag: metatag
# Deprecated https://github.com/EC-CUBE/ec-cube/pull/4987
admin.content.page_meta_metatag_placeholder: |
商品詳細ページでの記載例
<meta property="og:type" content="og:product" />
Expand Down Expand Up @@ -1596,7 +1597,7 @@ tooltip.content.page_file_name: ページの内容を記述したtwigテンプ
tooltip.content.page_source_code: テンプレートファイルを編集します。twigで記述します。
tooltip.content.page_layout: このページに適用するレイアウトを選択します。
tooltip.content.page_meta: ページのMETAタグの内容を指定できます。
tooltip.content.page_meta_tags: 自由にMETAタグを追加できます。twig内で利用されている変数も利用できます
tooltip.content.page_meta_tags: METAタグの出力をカスタマイズできます。twig内で利用されている変数も利用可能です。空欄の場合は、テンプレートフォルダの meta.twig ファイルが読み込まれます
tooltip.content.css_source_code: カスタマイズ用CSSファイルを編集します。CSSで記述します。
tooltip.content.js_source_code: カスタマイズ用JavaScriptファイルを編集します。JavaScriptで記述します。
tooltip.content.block_name: ブロックの管理用名称です。
Expand Down
2 changes: 1 addition & 1 deletion src/Eccube/Resource/template/admin/Content/page_edit.twig
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ file that was distributed with this source code.
</div>
</div>
<div class="col-10">
{{ form_widget(form.meta_tags, { attr : { placeholder : 'admin.content.page_meta_metatag_placeholder'|trans, rows : '10' }}) }}
{{ form_widget(form.meta_tags) }}
{{ form_errors(form.meta_tags) }}
</div>
</div>
Expand Down
8 changes: 5 additions & 3 deletions src/Eccube/Resource/template/default/default_frame.twig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ file that was distributed with this source code.
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="eccube-csrf-token" content="{{ csrf_token(constant('Eccube\\Common\\Constant::TOKEN_NAME')) }}">
<title>{{ BaseInfo.shop_name }}{% if subtitle is defined and subtitle is not empty %} / {{ subtitle }}{% elseif title is defined and title is not empty %} / {{ title }}{% endif %}</title>
{% if Page.meta_tags is not empty %}
{{ include(template_from_string(Page.meta_tags)) }}
{% else %}
{{ include('meta.twig') }}
{% endif %}
{% if Page.author is not empty %}
<meta name="author" content="{{ Page.author }}">
{% endif %}
Expand All @@ -27,9 +32,6 @@ file that was distributed with this source code.
{% if Page.meta_robots is not empty %}
<meta name="robots" content="{{ Page.meta_robots }}">
{% endif %}
{% if Page.meta_tags is not empty %}
{{ include(template_from_string(Page.meta_tags)) }}
{% endif %}
<link rel="icon" href="{{ asset('assets/img/common/favicon.ico', 'user_data') }}">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
Expand Down
28 changes: 28 additions & 0 deletions src/Eccube/Resource/template/default/meta.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{% if Product is defined %}
{% set meta_og_type = "og:product" %}
{% set meta_description = Product.description_list | default(Product.description_detail) | default(Page.description) %}
{% set meta_canonical = url('product_detail', {'id': Product.id}) %}
<meta property="og:title" content="{{ Product.name }}" />
<meta property="og:image" content="{{ absolute_url(asset(Product.main_list_image|no_image_product, 'save_image')) }}" />
<meta property="product:price:amount" content="{{ Product.getPrice02IncTaxMin }}"/>
<meta property="product:price:currency" content="{{ eccube_config.currency }}"/>
<meta property="product:product_link" content="{{ url('product_detail', {'id': Product.id}) }}"/>
<meta property="product:retailer_title" content="{{ BaseInfo.shop_name }}"/>
{% elseif Category is defined %}
{% set meta_og_type = 'article' %}
{% set meta_description = Page.description %}
{% set meta_canonical = url('product_list', {'category_id': Category.id|default(null)}) %}
{% elseif Page is defined %}
{% set meta_og_type = (app.request.get('_route') == 'homepage') ? 'website' : 'article' %}
{% set meta_description = Page.description %}
{% endif %}
<meta property="og:type" content="{{ meta_og_type }}"/>
<meta property="og:site_name" content="{{ BaseInfo.shop_name }}"/>
{% if meta_description|default() %}
<meta name="description" content="{{ meta_description|striptags|slice(0,120) }}">
<meta property="og:description" content="{{ meta_description|striptags|slice(0,120) }}"/>
{% endif %}
{% if meta_canonical|default() %}
<meta property="og:url" content="{{ meta_canonical }}"/>
<link rel="canonical" href="{{ meta_canonical }}"/>
{% endif %}
65 changes: 65 additions & 0 deletions tests/Eccube/Tests/Web/ProductControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Eccube\Entity\ProductClass;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\ClassCategoryRepository;
use Eccube\Repository\ProductRepository;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\HttpKernel\Client;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
Expand All @@ -28,6 +29,11 @@ class ProductControllerTest extends AbstractWebTestCase
*/
private $baseInfoRepository;

/**
* @var ProductRepository
*/
private $productRepository;

/**
* @var ClassCategoryRepository
*/
Expand All @@ -37,6 +43,7 @@ public function setUp()
{
parent::setUp();
$this->baseInfoRepository = $this->container->get(BaseInfoRepository::class);
$this->productRepository = $this->container->get(ProductRepository::class);
$this->classCategoryRepository = $this->container->get(ClassCategoryRepository::class);
}

Expand Down Expand Up @@ -250,4 +257,62 @@ public function testProductFavoriteAddThroughLogin()
$html = $crawler->filter('div.ec-productRole__profile')->html();
$this->assertContains('お気に入りに追加済です', $html);
}

/**
* 一覧ページ metaタグのテスト
*/
public function testMetaTagsInListPage()
{
// カテゴリ指定なし
$url = $this->generateUrl('product_list', [], UrlGeneratorInterface::ABSOLUTE_URL);
$crawler = $this->client->request('GET', $url);
$this->assertEquals('article', $crawler->filter('meta[property="og:type"]')->attr('content'));
$this->assertEquals($url, $crawler->filter('link[rel="canonical"]')->attr('href'));
$this->assertEquals($url, $crawler->filter('meta[property="og:url"]')->attr('content'));

// カテゴリ指定あり
$url = $this->generateUrl('product_list', ['category_id' => 1], UrlGeneratorInterface::ABSOLUTE_URL);
$crawler = $this->client->request('GET', $url);
$this->assertEquals($url, $crawler->filter('link[rel="canonical"]')->attr('href'));
}

/**
* 詳細ページ metaタグのテスト
*/
public function testMetaTagsInDetailPage()
{
$product = $this->productRepository->find(2); /** @var Product $product */
$description_detail = 'またそのなかでいっしょになったたくさんのひとたち、ファゼーロとロザーロ、羊飼のミーロや、顔の赤いこどもたち、地主のテーモ、山猫博士のボーガント・デストゥパーゴなど、いまこの暗い巨きな石の建物のなかで考えていると、みんなむかし風のなつかしい青い幻燈のように思われます。';
$description_list = 'では、わたくしはいつかの小さなみだしをつけながら、しずかにあの年のイーハトーヴォの五月から十月までを書きつけましょう。';

// 商品に description_list と description_detail を設定
// → meta descriotion には description_listが設定される
$product->setDescriptionList($description_list);
$product->setDescriptionDetail($description_detail);
$this->entityManager->flush();
$expected_desc = mb_substr($description_list, 0, 120, 'utf-8');

$url = $this->generateUrl('product_detail', ['id' => 2], UrlGeneratorInterface::ABSOLUTE_URL);
$imgPath = $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL) . 'html/upload/save_image/' . $product->getMainListImage()->getFileName();

$crawler = $this->client->request('GET', $url);

$this->assertEquals($expected_desc, $crawler->filter('meta[name="description"]')->attr('content'));
$this->assertEquals($expected_desc, $crawler->filter('meta[property="og:description"]')->attr('content'));
$this->assertEquals('og:product', $crawler->filter('meta[property="og:type"]')->attr('content'));
$this->assertEquals($url, $crawler->filter('link[rel="canonical"]')->attr('href'));
$this->assertEquals($url, $crawler->filter('meta[property="og:url"]')->attr('content'));
$this->assertEquals($imgPath, $crawler->filter('meta[property="og:image"]')->attr('content'));

// 商品の description_list を削除
// → meta description には description_detail が設定される
$product->setDescriptionList(null);
$this->entityManager->flush();
$expected_desc = mb_substr($description_detail, 0, 120, 'utf-8');

$crawler = $this->client->request('GET', $url);

$this->assertEquals($expected_desc, $crawler->filter('meta[name="description"]')->attr('content'));
$this->assertEquals($expected_desc, $crawler->filter('meta[property="og:description"]')->attr('content'));
}
}
26 changes: 26 additions & 0 deletions tests/Eccube/Tests/Web/TopControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

namespace Eccube\Tests\Web;

use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\PageRepository;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class TopControllerTest extends AbstractWebTestCase
{
public function testRoutingIndex()
Expand All @@ -27,4 +31,26 @@ public function testCheckFavicon()
$node = $crawler->filter('link[rel=icon]');
$this->assertEquals('/html/user_data/assets/img/common/favicon.ico', $node->attr('href'));
}

/**
* TOPページ metaタグのテスト
*/
public function testMetaTags()
{
// description を設定
$description = 'あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。';
$page = $this->container->get(PageRepository::class)->getByUrl('homepage');
$page->setDescription($description);
$this->entityManager->flush();

$shopName = $this->container->get(BaseInfoRepository::class)->get()->getShopName();
$expected_desc = mb_substr($description, 0, 120, 'utf-8');

$crawler = $this->client->request('GET', $this->generateUrl('homepage'));

$this->assertEquals($shopName, $crawler->filter('meta[property="og:site_name"]')->attr('content'));
$this->assertEquals('website', $crawler->filter('meta[property="og:type"]')->attr('content'));
$this->assertEquals($expected_desc, $crawler->filter('meta[name="description"]')->attr('content'));
$this->assertEquals($expected_desc, $crawler->filter('meta[property="og:description"]')->attr('content'));
}
}

0 comments on commit ad660fe

Please sign in to comment.