AMP
  • 網站

產品頁面

簡介

此範例展示如何在 AMP HTML 中建立產品頁面。

Metadata

頁面索引需要 schema.org 標記,類型如下:Type、AggregateRating、Offers。瞭解更多

<script type="application/ld+json">
{
    "@context": "http://schema.org/",
    "@type": "Product",
    "name": "Apple",
    "image": "https://amp.dev.org.tw/static/samples/img/golden_apple1_1024x682.jpg",
    "description": "Lorem ipsum",
    "mpn": "925872",
    "brand": {
        "@type": "Fruit",
        "name": "Apple"
    },
    "aggregateRating": {
        "@type": "AggregateRating",
        "ratingValue": "4.4",
        "reviewCount": "88"
    },
    "offers": {
        "@type": "Offer",
        "priceCurrency": "USD",
        "price": "1.99",
        "priceValidUntil": "2020-11-05",
        "itemCondition": "http://schema.org/UsedCondition",
        "availability": "http://schema.org/InStock",
        "seller": {
            "@type": "Retail",
            "name": "AMP by Example"
        }
    }
}
</script>

使用 amp-sidebar 元件,讓顧客有機會快速跳轉到您的任何產品類別。

<amp-sidebar id="drawermenu" layout="nodisplay">
  <a href="/" class="caps text-decoration-none block p1">Products</a>
  <hr/>
  <a class="caps text-decoration-none block p1" href="/samples_templates/product_browse_page/preview/">Fruit</a>
  <a class="caps text-decoration-none block p1" href="/samples_templates/product_browse_page/preview/">Vegetable</a>
  <a class="caps text-decoration-none block p1" href="/samples_templates/product_browse_page/preview/">More</a>
</amp-sidebar>

AMP 支援表單,這表示您可以直接將產品搜尋整合到您的 AMP 中。試著搜尋「Apple」。

您可以使用 CSS3 動畫來豐富您的頁面。當搜尋框聚焦時,展開的文字欄位僅使用 CSS 實作。

<div class="header">
  <a id="sample-menu" on="tap:drawermenu.toggle">
    <amp-img srcset="/static/samples/img/ic_menu_white_1x_web_24dp.png 1x, /static/samples/img/ic_menu_white_2x_web_24dp.png 2x"
            width="24" height="24"
            alt="navigation"></amp-img>
  </a>
  <form method="GET" action="/documentation/examples/api/search" target="_top">
    <input name="search" type="search" placeholder="Search">
    <a id="sample-logo" href="/">Product</a>
    <input type="submit" value="">
  </form>
</div>

社群分享

「社群分享」擴充功能為分享按鈕提供通用介面。如要進一步瞭解 amp-social-share,請按這裡

<div class="m1">
  <amp-social-share type="twitter"
                    width="30"
                    height="22"></amp-social-share>
  <amp-social-share type="facebook"
                    width="30"
                    height="22"
                    data-attribution="254325784911610"></amp-social-share>
  <amp-social-share type="email"
                    width="30"
                    height="22"></amp-social-share>
  <amp-social-share type="pinterest"
                    width="33"
                    height="22"></amp-social-share>
</div>

影片

AMP 支援廣泛的影片平台。這裡我們使用 amp-youtube 來顯示產品影片。如要查看所有支援影片平台的概覽,請按這裡

在此範例中,我們不會將影片直接嵌入到頁面中,而是使用 amp-lightbox 元件在燈箱中顯示。如要進一步瞭解 amp-lightbox,請按這裡

<button class="ampstart-btn caps m1 mb3" on="tap:watch-video-lightbox" >
  Show Video
</button>

在桌面上,我們新增了類似膠片條的幻燈片預覽。每種產品顏色都有自己的圖片庫和幻燈片預覽。我們使用 amp-bind 來更新頁面,以選擇對應於所選顏色的圖片庫和圖片預覽。我們透過使用 amp-selector 實現顏色選擇。請在下方的「產品頁面」章節中查看更多文件和資訊。

綠色是頁面載入時圖庫的預設顏色。按一下預覽圖片將透過輕觸動作 on="tap:AMP.setState({product: {selectedSlideForGreen: 0}})" 在圖庫中顯示圖片。

請參閱下方以取得更多關於我們如何使用 amp-bind 的資訊。

<div class="product-gallery">
  <ul [hidden]="product.selectedColor != 'green'">
    <li>
      <amp-img on="tap:AMP.setState({product: {selectedSlideForGreen: 0}})"
                src="/static/samples/img/green_apple_1_60x40.jpg"
                width="60" height="40"
                class="selected"
                [class]="product.selectedSlideForGreen == 0 ? 'selected' : '' "
                tabindex="0" role="button">
      </amp-img>
    </li>
    <li>
      <amp-img on="tap:AMP.setState({product: {selectedSlideForGreen: 1}})"
                src="/static/samples/img/green_apple_2_60x40.jpg"
                width="60" height="40"
                [class]="product.selectedSlideForGreen == 1 ? 'selected' : '' "
                tabindex="1" role="button">
      </amp-img>
    </li>
  </ul>

  <ul hidden [hidden]="product.selectedColor != 'golden'">
    <li>
      <amp-img on="tap:AMP.setState({product: {selectedSlideForGolden: 0}})"
              src="/static/samples/img/product1_alt1_60x40.jpg"
               width="60" height="40"
               class="selected fadeIn"
               [class]="product.selectedSlideForGolden == 0 ? 'selected fadeIn' : '' "
               tabindex="0" role="button">
      </amp-img>
    </li>
  </ul>

  <ul hidden [hidden]="product.selectedColor != 'red'">
    <li>
      <amp-img on="tap:AMP.setState({ product: {selectedSlideForRed : 0}})"
               src="/static/samples/static/samples/img/red_apple_1_60x40.jpg"
               width="60" height="40"
               class="selected fadeIn"
               [class]="product.selectedSlideForRed == 0 ? 'selected fadeIn' : '' "
               tabindex="0" role="button">
      </amp-img>
    </li>
    <li>
      <amp-img on="tap:AMP.setState({ product: {selectedSlideForRed : 1}})"
               src="/static/samples/static/samples/img/red_apple_2_60x46.jpg"
               width="60" height="40"
               [class]="product.selectedSlideForRed == 1 ? 'selected' : '' "
               tabindex="1" role="button">
      </amp-img>
    </li>
  </ul>
</div>

amp-carousel 元件非常適合用於產品圖片庫。如要瞭解 amp-carousel 元件的運作方式,請按這裡

請注意我們如何使用變數 selectedSlideForGreenselectedColor 的值來綁定到 slideclass

<div class="product-gallery">

  <amp-carousel id="green-apple-carousel"
          width="1024" height="682"
          layout="responsive"
          type="slides"
          [slide]="product.selectedSlideForGreen"
          on="slideChange: AMP.setState({product: {selectedSlideForGreen: event.index}})"
          class="fadeIn"
          [hidden]="product.selectedColor != 'green'">
    <amp-img src="/static/samples/img/green_apple_1_1024x682.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
    </amp-img>
    <amp-img src="/static/samples/img/green_apple_2_1024x685.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
    </amp-img>
  </amp-carousel>

  <amp-carousel id="golden-apple-carousel"
          width="1024" height="682"
          layout="responsive"
          type="slides"
          [slide]="product.selectedSlideForGolden"
          on="slideChange: AMP.setState({product: {selectedSlideForGolden: event.index}})"
          hidden
          class="fadeIn"
          [hidden]="product.selectedColor != 'golden'">
      <amp-img src="/static/samples/img/golden_apple1_1024x682.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
      </amp-img>
  </amp-carousel>

  <amp-carousel id="red-apple-carousel"
          width="1024" height="682"
          layout="responsive"
          type="slides"
          [slide]="product.selectedSlideForRed"
          on="slideChange: AMP.setState({product: {selectedSlideForRed: event.index}})"
          hidden
          class="fadeIn"
          [hidden]="product.selectedColor != 'red'">
      <amp-img src="/static/samples/img/red_apple_1_1024x682.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
      </amp-img>
      <amp-img src="/static/samples/img/red_apple_2_1024x793.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
      </amp-img>
  </amp-carousel>
</div>

全螢幕圖片

amp-image-lightbox 元件允許使用者展開圖片以填滿視窗。透過點擊產品圖片庫中的每張圖片,使用者可以使用全螢幕檢視產品圖片。如要瞭解更多資訊,請按這裡

<amp-image-lightbox id="gallery-lightbox" layout="nodisplay">
  <div on="tap:gallery-lightbox.close" role="button"
      tabindex="0">
      <button class="ampstart-btn caps m2 close-gallery-button" on="tap:gallery-lightbox.close"
        role="button" tabindex="0">
        Close
      </button>
  </div>
</amp-image-lightbox>

產品配置

我們使用 amp-state 元件 (屬於 amp-bind 的一部分)

來根據顏色和尺寸配置產品價格。當您在顏色之間切換時,如果先前選擇的尺寸在新顏色中不可用,我們也會為每種產品配置 defaultSize

<amp-state id="product">
  <script type="application/json">
  {
    "selectedColor": "green",
    "selectedSize": "S",
    "selectedSlideForRed": 0,
    "selectedSlideForGolden": 0,
    "selectedSlideForGreen": 0,
    "moreItemsPageIndex": 0,
    "hasMorePages": true,
    "green": {
      "id": "1",
      "sizes": {
        "S": "$5.99",
        "M": "$5.99",
        "L": "unavailable"
      },
      "defaultSize": "S"
    },
    "golden": {
      "id": "2",
      "sizes": {
        "S": "$9.99",
        "M": "unavailable",
        "L": "$9.99"
      },
      "defaultSize": "L"
    },
    "red": {
      "id": "3",
      "sizes": {
        "S": "$7.99",
        "M": "$7.99",
        "L": "$7.99"
      },
      "defaultSize": "M"
    }
  }
  </script>
</amp-state>

產品價格

我們使用 amp-bind 來更新產品價格

,具體取決於所選顏色。

我們將 text 屬性綁定到表達式 product[product.selectedColor].sizes[product.selectedSize] 的值。product 是「產品配置」章節中說明的 amp-state json ID。

請注意我們如何將 $1.99 值設定為價格的預設值:表達式不會在頁面載入時評估。

我們將 amp-selectoramp-bind 一起使用,以更新頁面以顯示價格、尺寸可用性、圖片庫和圖片預覽。每次您選擇顏色時,我們都會使用 {selectedColor: event.targetOption} 呼叫 AMP.setState。這會觸發所有綁定到 selectedColor 的屬性和元素進行更新:價格 (綁定到 [text] 屬性)、圖片庫、圖片預覽和尺寸選擇器 (全部綁定到 [class])。

價格:$5.99

<p class="price-description">Price:
  <span [text]="product[product.selectedColor].sizes[product.selectedSize]">$5.99</span>
</p>

產品頁面

「加入購物車」動作是使用 amp-form 實作的。在我們的範例中,我們使用 amp-selector 來選擇不同的產品屬性。按下「加入購物車」按鈕會使用您選擇的屬性將產品新增到購物車頁面。請注意,按鈕網址包含查詢 clientId={{ClientId}}。如果商品成功新增到購物車,我們會將使用者重新導向至購物車頁面。重新導向目標是透過伺服器表單回應中的標頭設定 (提交後重新導向)

access-control-expose-headers:AMP-Access-Control-Allow-Source-Origin,AMP-Redirect-To amp-redirect-to:http://ampbyexample.com/shopping_cart/?clientid=amp-123456789

我們使用 CLIENT_ID 變數來識別使用者,這可在重複瀏覽 AMP 頁面 (透過 AMP 快取或原始主機) 之間儲存購物車。這個變數可以透過宣告具有 default-value="CLIENT_ID(cart) 的隱藏輸入值在 amp-form 內部使用。如要進一步瞭解變數替換,請按這裡

  • 1
  • 2
  • 3
  • S
  • M
  • L
<form id="order" method="POST"
      action-xhr="/documentation/examples/e-commerce/shopping_cart/add-to-cart"
      target="_top" class="flex flex-wrap m1">
  <div class="items-center flex">
    <label for="color">Color:</label>
    <amp-selector name="color"
            layout="container"
            [selected]="product.selectedColor"
            on="select:AMP.setState({
              product: {
                selectedColor: event.targetOption,
                selectedSlideForRed: 0,
                selectedSlideForGreen: 0,
                selectedSlideForYellow: 0,
                selectedSize: product[event.targetOption].sizes[product.selectedSize] != 'unavailable' ? product.selectedSize : product[event.targetOption].defaultSize
              }
            })">
      <ul class="p0 m1">
        <li>
          <div option="green" selected class="square green"></div>
        </li>
        <li>
          <div option="golden" class="square golden"></div>
        </li>
        <li>
          <div option="red" class="square red"></div>
        </li>
      </ul>
    </amp-selector>
  </div>
  <div class="items-center flex">
    <label for="quantity">Quantity:</label>
    <amp-selector name="quantity" layout="container">
      <ul class="p0 m1">
        <li option="1" selected>1</li>
        <li option="2">2</li>
        <li option="3">3</li>
      </ul>
    </amp-selector>
  </div>
  <div class="items-center flex">
    <label for="size">Size:</label>
    <amp-selector name="size" layout="container"
            on="select:AMP.setState({ product: {selectedSize: event.targetOption}})"
            [selected]="(product[product.selectedColor].sizes[product.selectedSize] != 'unavailable')
                ? product.selectedSize
                : product[product.selectedColor].defaultSize">
      <ul class="p0 m1">
        <li option="S" class=""
            [class]="(product[product.selectedColor].sizes['S'] != 'unavailable')
                ? ''
                : 'unavailable'">S</li>
        <li option="M" class="" selected
            [class]="(product[product.selectedColor].sizes['M'] != 'unavailable')
                ? ''
                : 'unavailable'">M</li>
        <li option="L" class="unavailable"
            [class]="(product[product.selectedColor].sizes['L'] != 'unavailable')
                ? ''
                : 'unavailable'">L</li>
      </ul>
    </amp-selector>
  </div>
  <div class="items-center flex my1">
    <input type="submit" class="ampstart-btn caps" name="add-to-cart" value="add to cart">
  </div>
  <input type="hidden" name="name" value="Apple">
  <input type="hidden" name="price" value="$1.99" [value]="product[product.selectedColor].sizes[product.selectedSize]">
  <input type="hidden" name="id" value="1" [value]="product[product.selectedColor].id">
  <input name="clientId" type="hidden" value="CLIENT_ID(cart)" data-amp-replace="CLIENT_ID">
  <div submit-error>
    <template type="amp-mustache">
      Error! Looks like something went wrong with your shopping cart, please try to add an item again. {{error}}
    </template>
  </div>
</form>

標籤面板

使用樣式設定為標籤面板的 amp-selector 來新增關於您產品的其他資料。如要瞭解如何在 AMP 中實作標籤,請按這裡

水果富含維生素和礦物質。Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
食用前務必清洗水果。Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
尺寸可能有所不同。Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<amp-selector role="tablist"
layout="container"
class="ampTabContainer ampstart-headerbar-nav" keyboard-select-mode="select">
<div role="tab"
  class="tabButton h4 ampstart-nav-item"
  selected
  option="a">ABOUT</div>
<div role="tabpanel"
    class="tabContent p1 p">Fruit is rich in vitamins and minerals. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
<div role="tab"
  class="tabButton h4 ampstart-nav-item"
  option="b">SPECS</div>
<div role="tabpanel"
  class="tabContent p1 p">Always wash fruit before eating. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
<div role="tab"
    class="tabButton h4 ampstart-nav-item"
    option="c">SIZE</div>
<div role="tabpanel"
    class="tabContent p1 p">Size may vary. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
</amp-selector>

透過 AMP,您可以輕鬆提取不同的最新優惠或重點,而無需更改頁面。若要這麼做,只需使用 amp-list 向 JSON 端點觸發 CORS 要求,該端點會提供相關產品的清單。這些產品會填入用戶端上的 amp-mustache 範本中。如要進一步瞭解 amp-list,請按這裡

<amp-list class="items m1"
          width="auto"
          height="145"
          layout="fixed-height"
          src="/static/samples/json/related_products.json"
          [src]="myState.items"
          binding="no"
          id="show-more-list">
  <template type="amp-mustache">
    <a class="text-decoration-none p1"
      href="/documentation/examples/e-commerce/product_page/preview/">
      <amp-img width="70.31"
               height="46.8"
               layout="fixed"
               alt="{{name}}"
               src="{{img}}"></amp-img>
             <p class="name">{{name}}</p>
             <p class="star">{{{stars}}}</p>
             <p class="price">${{price}}</p>
     </a>
  </template>
</amp-list>

雖然目前在 AMP 中無法進行無限捲動,但您可以使用 amp-bind 動態變更 amp-list 的 src,並在頁面中新增更多項目。我們將 src 屬性綁定到 amp-state 元件的 ID,以便 amp-list 將該元件中的項目用作 srcamp-state 初始值是透過將 src 值設定為 amp-list 使用的相同端點來設定。每次使用者按一下「顯示更多」按鈕時,我們都會將項目附加到 amp-state,詳情請參閱下方。

<amp-state id="myState" src="/static/samples/json/related_products.json">
</amp-state>

您可以使用 amp-formsubmit-success 事件來顯示或隱藏「顯示更多」按鈕:請注意我們如何根據伺服器回應將 hasMorePages 變數設為 false。

<form method="GET"
    action="/documentation/examples/api/json/more_related_products_page"
    action-xhr="/documentation/examples/api/json/more_related_products_page"
    target="_top"
    on="submit-success: AMP.setState({
      myState: { items: myState.items.concat(event.response.items)},
      product: {moreItemsPageIndex: product.moreItemsPageIndex + 1,
                hasMorePages: event.response.hasMorePages}
    });">
  <input type="hidden" name="moreItemsPageIndex" value="0" [value]="product.moreItemsPageIndex">
  <input type="submit" value="Show more"
    class="ampstart-btn caps m1 mb3"
    [hidden] = "!product.hasMorePages">
</form>

使用者分析

分析必須在 body 中配置。這裡我們使用 Google Analytics (分析) 來追蹤網頁瀏覽量。

<amp-analytics type="googleanalytics">
  <script type="application/json">
      {
        "vars": {
            "account": "UA-73836974-1"
        },
        "triggers": {
            "default pageview": {
                "on": "visible",
                "request": "pageview",
                "vars": {
                    "title": "Product"
                }
            }
        }
    }
  </script>
</amp-analytics>
需要更多說明嗎?

如果此頁面上的說明未能涵蓋您的所有問題,請隨時與其他 AMP 使用者聯繫,討論您的確切使用案例。

前往 Stack Overflow
未說明的特色?

AMP 專案強烈鼓勵您的參與和貢獻!我們希望您能成為我們開放原始碼社群的持續參與者,但我們也歡迎您針對您特別感興趣的問題做出一次性貢獻。

在 GitHub 上編輯範例