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 的一部分)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 是「產品設定」章節中說明的 ID amp-state json。

請注意我們如何將 $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 來選取不同的產品屬性。按下 ADD TO CART 按鈕會使用您選取的屬性將產品新增至購物車頁面。請注意,按鈕網址包含查詢 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 快取或原始主機) 之間儲存購物車。這個變數可在 amp-form 內使用,方法是宣告具有 default-value="CLIENT_ID(cart) 的隱藏輸入值。在此處進一步瞭解變數替換詳情

  • 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 發出 CORS 要求至 JSON 端點,以提供相關產品列表。這些內容會填入用戶端上的 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 將該元件中的項目當做 src 使用。amp-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 上編輯範例