AMP
  • 網站

產品頁面

簡介

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

中繼資料

頁面索引需要 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 搭配使用,以更新頁面來顯示價格、尺寸供應情況、圖庫和圖片預覽圖。每次您選取顏色時,我們會呼叫 AMP.setState 並使用 {selectedColor: event.targetOption}。這會觸發繫結至 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 快取或原始主機) 時儲存購物車。您可以透過宣告具有隱藏輸入值的 hidden input value 與 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) 中設定 Analytics (分析)。在這裡,我們使用 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 上編輯範例