Embed components: The elements, styling, embed domains and events # Quick start > Put DPD products, add to cart buttons and a cart on your own website. DPD’s embed components are HTML elements you paste into your own site: product cards, add to cart buttons, a cart and a checkout button. Your visitors browse and fill their cart on your page. When they check out, they go to your store’s hosted checkout to pay. The examples on these pages are live. They sell from DPD’s demo store, which runs in test mode, so go ahead and add things to the cart. ## 1. Add dpd.js to your page [Section titled “1. Add dpd.js to your page”](#1-add-dpdjs-to-your-page) Every DPD store serves a copy of `dpd.js` from its cart host. Put the script tag in your page’s ``, with your store’s subdomain in place of `STORE`: ```html ``` ## 2. Allow your website [Section titled “2. Allow your website”](#2-allow-your-website) The components only work on sites you’ve allowed. Your store’s website (the one in its settings) is allowed already. For any other domain, add it in the DPD admin under **Settings > Checkout > Embed domains**. See [Where they work](embed-domains/) for the details. ## 3. Add a product [Section titled “3. Add a product”](#3-add-a-product) `` shows a product’s image, name and price, with an add to cart button. Its `product` is the product’s ID, which you’ll find in the DPD admin (it’s also in the button code page’s components tab). ```html ``` Click **Add to cart** and the cart opens in a drawer at the side of the page. ## 4. Add a cart button [Section titled “4. Add a cart button”](#4-add-a-cart-button) Put `` in your site’s header. It shows how many things are in the cart, and opens the drawer. ```html ``` That’s a working shop. The drawer has the cart’s items, quantities, coupon field, totals and a checkout button. ## The elements [Section titled “The elements”](#the-elements) | Element | What it is | | ------------------------------------------- | -------------------------------------------------------- | | [``](product/) | A product card, or the full product with its description | | [``](add-to-cart/) | An add to cart button, with your own label | | [``](cart/) | The cart, right in your page | | [``](cart-button/) | A cart icon with the item count, which opens the drawer | | [``](checkout-button/) | Goes straight to the hosted checkout | They all share one cart, the same one DPD’s [classic buy buttons](../buttons/) use, so you can mix them on a page. ## More than one store [Section titled “More than one store”](#more-than-one-store) Each element sells from the store whose `dpd.js` you loaded. To sell from another store on the same page, give the element a `store` attribute with that store’s cart host: ```html ``` `store` also takes a full origin, like `https://shop.example.com` for a store on its own domain. Each store gets its own cart and drawer. # > An add to cart button for a DPD product, with your own label. `` is a button that adds a product to the cart and opens the drawer. Use it when you’ve already got your own product page and just need the button. Whatever you put inside it is the button’s label. Leave it empty for “Add to cart” in your store’s language. ```html Get the ebook ``` ## Attributes [Section titled “Attributes”](#attributes) | Attribute | | | ------------- | --------------------------------------------------------------------------- | | `product` | **Required.** The product’s ID. | | `price-point` | The ID of one of the product’s prices. Leave it off for the default price. | | `quantity` | How many to add. Defaults to 1. | | `store` | The store to sell from. See [More than one store](../#more-than-one-store). | ## Upsells, license agreements and cross-sells [Section titled “Upsells, license agreements and cross-sells”](#upsells-license-agreements-and-cross-sells) If the product has an upsell, a license agreement or a cross-sell set up in the admin, the button shows it in a dialog before (or after) the product goes in the cart, the same as the hosted cart does. Try these two: the first offers an upgrade, and the second asks you to accept a license. ```html Weeknight Sauces Weekly Meal Planner ``` The button says **Sold out**, and can’t be clicked, when the product is out of stock. Its part is `button`. # > Show the DPD cart right in your page. `` puts the cart in your page: each item with its quantity and a remove link, the coupon field, the totals and a checkout button. It’s the same cart the drawer shows. Use it for a cart page on your own site. Add something first, then watch the cart below fill in. ```html Steak Rub Spice Tin ``` ## Attributes [Section titled “Attributes”](#attributes) | Attribute | | | --------- | --------------------------------------------------------------------- | | `target` | `_blank` opens the checkout in a new tab. | | `store` | The store’s cart. See [More than one store](../#more-than-one-store). | ## Good to know [Section titled “Good to know”](#good-to-know) * The coupon field only shows when your store has coupons turned on. * When something in the cart needs shipping, the totals say “Calculated at checkout” for shipping. The hosted checkout works it out from the address. * Every element on the page shows the same cart, and so do other tabs open on your site. Change a quantity here and the cart button’s count changes too. Its parts are `cart`, `item`, `totals` and `checkout-button`. # > A cart icon with the number of items, which opens the cart drawer. `` is a cart icon with a badge for the number of items in the cart. Clicking it opens the cart drawer. Most sites put one in the header. ```html ``` ## Attributes [Section titled “Attributes”](#attributes) | Attribute | | | --------- | -------------------------------------------------------------------------------------------- | | `label` | Text to show beside the icon. Screen readers hear it with the item count (“Cart, Items: 2”). | | `store` | The store’s cart. See [More than one store](../#more-than-one-store). | You can also put the label inside the element, like `My bag`, if you want markup in it. Its parts are `button` and `badge`. # > A button that goes straight to your store's hosted checkout. `` sends the visitor to your store’s hosted checkout with their cart. It’s disabled while the cart is empty. The drawer and `` already have a checkout button, so you’ll only need this one for a layout of your own. Whatever you put inside it is the label. Leave it empty for “Checkout” in your store’s language. ```html Pay now ``` ## Attributes [Section titled “Attributes”](#attributes) | Attribute | | | --------- | --------------------------------------------------------------------- | | `target` | `_blank` opens the checkout in a new tab. | | `store` | The store’s cart. See [More than one store](../#more-than-one-store). | Its part is `button`. # Where they work > Which websites can use your store's embed components, and how to add more. A cart holds the customer’s name and email address once they’ve entered them, so DPD only lets your own websites use your store’s cart. The components work on: * your store’s website, the one set in its settings * your store’s cart host (`STORE.dpdcart.com`, or your own cart domain) * any domain you add in the DPD admin under **Settings > Checkout > Embed domains** In the embed domains list, `example.com` also covers `www.example.com`, and `*.example.com` covers every subdomain. ## When a site isn’t allowed [Section titled “When a site isn’t allowed”](#when-a-site-isnt-allowed) On any other site the components load, but tell visitors “This store’s cart isn’t available on this website.” dpd.js also logs which domain to add to the browser’s console, for you: ```plaintext dpd.js: shop.example.com isn't allowed to use the cart at https://STORE.dpdcart.com. Add it under Settings > Checkout > Embed domains in DPD to show the components here. ``` ## Testing on your own computer [Section titled “Testing on your own computer”](#testing-on-your-own-computer) `localhost` isn’t allowed by default. Add it to your embed domains while you build your site, and take it out when you’re done if you like. On a page served from `localhost` or `127.0.0.1`, **Continue shopping** on the hosted checkout can’t link back to your page. That works once your site is live. # Events and languages > Listen for cart changes from your own scripts, and how the components pick their language. ## Events [Section titled “Events”](#events) dpd.js fires two events on `window` that your own scripts can listen for. `dpd:cart` fires whenever the cart changes, including when it first loads: ```js window.addEventListener('dpd:cart', (event) => { const { store, itemCount, cart } = event.detail; document.querySelector('.my-cart-count').textContent = itemCount; }); ``` `dpd:added` fires after a product is added, which is handy for analytics: ```js window.addEventListener('dpd:added', (event) => { const { store, product } = event.detail; gtag('event', 'add_to_cart', { items: [{ item_id: product }] }); }); ``` | Field | | | ----------- | -------------------------------------------------------- | | `store` | The store’s origin, like `https://STORE.dpdcart.com`. | | `itemCount` | How many things are in the cart (`dpd:cart` only). | | `cart` | The cart: its items and totals (`dpd:cart` only). | | `product` | The ID of the product that was added (`dpd:added` only). | ## Languages [Section titled “Languages”](#languages) The components use your store’s language, the one set in its settings in the DPD admin. Their own words (Add to cart, Your cart, Checkout and so on) come in all 27 languages DPD’s cart supports. Product names, prices, upsell offers and license agreements are yours, so they show as you wrote them. A button with its own label, like `Jetzt kaufen`, keeps your label whatever the store’s language is. # > Show a DPD product on your site as a card, or in full with its description. `` shows a product from your store with an add to cart button. DPD fills in the image, name, price, stock and payment plan, so the page stays in step when you change the product in the admin. ```html ``` ## Attributes [Section titled “Attributes”](#attributes) | Attribute | | | ------------- | ------------------------------------------------------------------------------------ | | `product` | **Required.** The product’s ID. | | `price-point` | The ID of one of the product’s prices. Leave it off for the product’s default price. | | `layout` | `card` (the default) or `detail`. | | `link` | Add it (no value needed) to link the product’s name to its page on your store. | | `store` | The store to sell from. See [More than one store](../#more-than-one-store). | ## The detail layout [Section titled “The detail layout”](#the-detail-layout) `layout="detail"` shows the whole product: a large image, the description you wrote in the admin, and a quantity field when the product allows more than one. It’s made for a product page on your own site. The image sits beside the text when the element is at least 640px wide, and above it when it’s narrower. ```html ``` ## What else it does [Section titled “What else it does”](#what-else-it-does) * Shows **Sold out**, and disables the button, when the product is out of stock. * Shows “Only 3 left” when you track stock for the product. * Runs the product’s extra steps when it’s added: an upsell offer, a license agreement to accept, or a cross-sell offer. The product above has an upsell. * Shows a product that’s free as **Free**. To change how it looks, see [Styling](../styling/). The card’s parts are `card`, `image`, `name`, `name-link`, `price`, `description` and `button`. # Styling > Match DPD's embed components to your site with CSS custom properties and ::part(). Each component draws itself inside a shadow root, so your site’s CSS can’t accidentally break it (and its CSS can’t leak into your page). You style it in two ways: custom properties for colors, corners and the font, and `::part()` for anything more. ## Custom properties [Section titled “Custom properties”](#custom-properties) Set these on `:root` to style every component on the page, or on one element (or a wrapper) to style just that one. | Property | Default | Used for | | -------------------- | ---------------- | ----------------------------------------- | | `--dpd-primary` | `#2563eb` | Buttons, the cart badge, links | | `--dpd-primary-text` | `#ffffff` | Text on buttons | | `--dpd-surface` | `#ffffff` | Cards, the drawer and dialogs | | `--dpd-text` | `#1f2933` | Text | | `--dpd-muted` | `#6b7280` | Secondary text, like a price point’s name | | `--dpd-border` | `#e5e7eb` | Borders and dividers | | `--dpd-danger` | `#dc2626` | Errors and low stock | | `--dpd-success` | `#15803d` | Discounts in the totals | | `--dpd-radius` | `8px` | Corners | | `--dpd-font` | Your page’s font | Every component’s text | ```html
``` The drawer and dialogs live in a `` that dpd.js adds to the end of ``, so they only pick up properties you set on `:root` or `body`, or on `dpd-cart-overlay` itself. ## ::part() [Section titled “::part()”](#part) For anything the properties don’t cover, `::part()` reaches named pieces inside a component. You can use any CSS on a part, but not on what’s inside it. | Element | Parts | | ----------------------- | ---------------------------------------------------------------------- | | `` | `card`, `image`, `name`, `name-link`, `price`, `description`, `button` | | `` | `button` | | `` | `cart`, `item`, `totals`, `checkout-button` | | `` | `button`, `badge` | | `` | `button` | | `` | `backdrop`, `drawer`, `dialog` | ```html ``` A few more ideas: ```css /* square product cards with a shadow */ dpd-product::part(card) { border-radius: 0; box-shadow: 0 10px 24px -18px rgb(0 0 0 / 50%); } /* a bigger name on product pages */ dpd-product[layout="detail"]::part(name) { font-size: 2.5rem; } /* an accent stripe down the drawer */ dpd-cart-overlay::part(drawer) { border-left: 4px solid tomato; } ``` [castandcrumb.com](https://castandcrumb.com) is a demo shop styled this way from top to bottom.