docs: publish restructure (#3496)
* docs: added features and guides overview page * added image * added version 2 * added version 3 * added version 4 * docs: implemented new color scheme * docs: redesigned sidebar (#3193) * docs: redesigned navbar for restructure (#3199) * docs: redesigned footer (#3209) * docs: redesigned cards (#3230) * docs: redesigned admonitions (#3231) * docs: redesign announcement bar (#3236) * docs: redesigned large cards (#3239) * docs: redesigned code blocks (#3253) * docs: redesigned search modal and page (#3264) * docs: redesigned doc footer (#3268) * docs: added new sidebars + refactored css and assets (#3279) * docs: redesigned api reference sidebar * docs: refactored css * docs: added code tabs transition * docs: added new sidebars * removed unused assets * remove unusued assets * Fix deploy errors * fix incorrect link * docs: fixed code responsivity + missing icons (#3283) * docs: changed icons (#3296) * docs: design fixes to the sidebar (#3297) * redesign fixes * docs: small design fixes * docs: several design fixes after restructure (#3299) * docs: bordered icon fixes * docs: desgin fixes * fixes to code blocks and sidebar scroll * design adjustments * docs: restructured homepage (#3305) * docs: restructured homepage * design fixes * fixed core concepts icon * docs: added core concepts page (#3318) * docs: restructured homepage * design fixes * docs: added core concepts page * changed text of different components * docs: added architecture link * added missing prop for user guide * docs: added regions overview page (#3327) * docs: added regions overview * moved region pages to new structure * docs: fixed description of regions architecture page * small changes * small fix * docs: added customers overview page (#3331) * docs: added regions overview * moved region pages to new structure * docs: fixed description of regions architecture page * small changes * small fix * docs: added customers overview page * fix link * resolve link issues * docs: updated regions architecture image * docs: second-iteration fixes (#3347) * docs: redesigned document * design fixes * docs: added products overview page (#3354) * docs: added carts overview page (#3363) * docs: added orders overview (#3364) * docs: added orders overview * added links in overview * docs: added vercel redirects * docs: added soon badge for cards (#3389) * docs: resolved feedback changes + organized troubleshooting pages (#3409) * docs: resolved feedback changes * added extra line * docs: changed icons for restructure (#3421) * docs: added taxes overview page (#3422) * docs: added taxes overview page * docs: fix sidebar label * added link to taxes overview page * fixed link * docs: fixed sidebar scroll (#3429) * docs: added discounts overview (#3432) * docs: added discounts overview * fixed links * docs: added gift cards overview (#3433) * docs: added price lists overview page (#3440) * docs: added price lists overview page * fixed links * docs: added sales channels overview page (#3441) * docs: added sales overview page * fixed links * docs: added users overview (#3443) * docs: fixed sidebar border height (#3444) * docs: fixed sidebar border height * fixed svg markup * docs: added possible solutions to feedback component (#3449) * docs: added several overview pages + restructured files (#3463) * docs: added several overview pages * fixed links * docs: added feature flags + PAK overview pages (#3464) * docs: added feature flags + PAK overview pages * fixed links * fix link * fix link * fixed links colors * docs: added strategies overview page (#3468) * docs: automated upgrade guide (#3470) * docs: automated upgrade guide * fixed vercel redirect * docs: restructured files in docs codebase (#3475) * docs: restructured files * docs: fixed eslint exception * docs: finished restructure loose-ends (#3493) * fixed uses of backend * docs: finished loose ends * eslint fixes * fixed links * merged master * added update instructions for v1.7.12
This commit is contained in:
5
docs/content/plugins/analytics/index.mdx
Normal file
5
docs/content/plugins/analytics/index.mdx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Analytics Plugins
|
||||
|
||||
<DocCardList />
|
||||
213
docs/content/plugins/analytics/segment.md
Normal file
213
docs/content/plugins/analytics/segment.md
Normal file
@@ -0,0 +1,213 @@
|
||||
---
|
||||
description: 'Learn how to integrate Segment with the Medusa backend. Learn how to add custom tracking with Segment and Medusa.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Segment
|
||||
|
||||
In this document, you’ll learn about the [Segment plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-segment), what it does, and how to install and use it.
|
||||
|
||||
## Overview
|
||||
|
||||
[Segment](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-segment) is a powerful Customer Data Platform that allows users to collect, transform, send and archive their customer data.
|
||||
|
||||
Segment allows users to manage different tracking and marketing tools using one API and interface, making it very simple to try out and integrate with different services in your ecommerce stack.
|
||||
|
||||
Common integration use cases that can be implemented with Segment include:
|
||||
|
||||
- Google Analytics
|
||||
- Mailchimp
|
||||
- Zendesk
|
||||
- Data warehousing for advanced data analytics and segmentation through services like Snowflake
|
||||
|
||||
The Segment plugin in Medusa allows you to track ecommerce events and record them in Segment. Then, you can push these events to other destinations using Segment.
|
||||
|
||||
### Events That the Segment Plugin Tracks
|
||||
|
||||
By default, the Segment plugin tracks the following events:
|
||||
|
||||
1. `order.placed`: Triggered when an order is placed.
|
||||
2. `order.shipment_created`: Triggered when a shipment is created for an order.
|
||||
3. `claim.created`: Triggered when a new claim is created.
|
||||
4. `order.items_returned`: Triggered when an item in an order is returned.
|
||||
5. `order.canceled`: Triggered when an order is canceled.
|
||||
6. `swap.created`: Triggered when a swap is created.
|
||||
7. `swap.shipment_created`: Triggered when a shipment is created for a swap.
|
||||
8. `swap.payment_completed`: Triggered when payment for a swap is completed.
|
||||
|
||||
:::tip
|
||||
|
||||
Check out the [Event Reference](../../development/events/events-list.md) to learn about all available events in Medusa.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Backend
|
||||
|
||||
It is assumed you already have a Medusa backend installed. If not, please follow the [Quickstart guide](../../development/backend/install.mdx) to get started in minutes.
|
||||
|
||||
In addition, make sure to have Redis installed and configured with your Medusa backend. If not, follow [this documentation](../../development/backend/prepare-environment.mdx#redis) to install Redis and then [configure it](../../development/backend/configurations.md#redis).
|
||||
|
||||
### Segment Account
|
||||
|
||||
You need to [create a Segment account](https://app.segment.com/signup/) to follow along with the tutorial. Segment offers a free plan to get started quickly.
|
||||
|
||||
---
|
||||
|
||||
## Create a Segment Source
|
||||
|
||||
On your Segment dashboard, choose Catalog from the sidebar under Connections.
|
||||
|
||||

|
||||
|
||||
Then, in the catalog list find the Backend category and choose Node.js from the list.
|
||||
|
||||

|
||||
|
||||
This opens a new side menu. In the side menu, click on Add Source.
|
||||
|
||||

|
||||
|
||||
This opens a new page to create a Node.js source. Enter the name of the source then click Add Source.
|
||||
|
||||

|
||||
|
||||
On the new source dashboard, you should find a Write Key. You’ll use this key in the next section after you install the Segment plugin on your Medusa backend.
|
||||
|
||||

|
||||
|
||||
### Optional: Add Destination
|
||||
|
||||
After you create the Segment source, you can add destinations. This is where the data is sent when you send them to Segment. You can add more than one destination.
|
||||
|
||||
To add a destination, on the same Segment source page, click on Add Destination in the Destinations section.
|
||||
|
||||

|
||||
|
||||
You can then choose from a list of destinations such as Google Universal Analytics or Facebook Pixel.
|
||||
|
||||

|
||||
|
||||
The process of integrating each destination is different, so you must follow the steps detailed in Segment for each destination you choose.
|
||||
|
||||
---
|
||||
|
||||
## Install the Segment Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the Segment plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-segment
|
||||
```
|
||||
|
||||
Then, add the following environment variable:
|
||||
|
||||
```bash
|
||||
SEGMENT_WRITE_KEY=<YOUR_SEGMENT_WRITE_KEY>
|
||||
```
|
||||
|
||||
Where `<YOUR_SEGMENT_WRITE_KEY>` is the Write Key shown on the page of the Segment source you created in the previous section.
|
||||
|
||||
Finally, in `medusa-config.js`, add the following new item to the `plugins` array:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-plugin-segment`,
|
||||
options: {
|
||||
write_key: process.env.SEGMENT_WRITE_KEY,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test the Plugin
|
||||
|
||||
Run your backend with the following command:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run start
|
||||
```
|
||||
|
||||
Then, try triggering one of the [mentioned events earlier in this document](#events-that-the-segment-plugin-tracks). For example, you can place an order either using the [REST APIs](https://docs.medusajs.com/api/store) or using the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts.
|
||||
|
||||
After you place an order, on the Segment source that you created, click on the Debugger tab. You should see at least one event triggered for each order you place. If you click on the event, you can see the order details are passed to the event.
|
||||
|
||||

|
||||
|
||||
If you added a destination, you can also check your destination to make sure the data is reflected there.
|
||||
|
||||
:::note
|
||||
|
||||
If the data is not appearing on the destination, the issue is related to your configuration between the Segment source and destination and not related to the Segment plugin. Go over the steps that Segment showed you when you added the destination to figure out the issue.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Add Custom Tracking
|
||||
|
||||
In some cases, you might want to track more events or custom events. You can do that using the `SegmentService` provided by the Segment Plugin.
|
||||
|
||||
For example, you can add the following subscriber to listen to the `customer.created` event and add tracking for every customer created:
|
||||
|
||||
```jsx title=src/subscribers/customer.ts
|
||||
class CustomerSubscriber {
|
||||
constructor({ segmentService, eventBusService }) {
|
||||
this.segmentService = segmentService
|
||||
|
||||
eventBusService.subscribe(
|
||||
"customer.created",
|
||||
this.handleCustomer
|
||||
)
|
||||
}
|
||||
|
||||
handleCustomer = async (data) => {
|
||||
const customerData = data
|
||||
delete customerData["password_hash"]
|
||||
|
||||
this.segmentService.track({
|
||||
event: "Customer Created",
|
||||
userId: data.id,
|
||||
properties: customerData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default CustomerSubscriber
|
||||
```
|
||||
|
||||
You resolve the `SegmentService` using dependency injection. Then, when the `customer.created` event is triggered, you use the `track` method available in the `SegmentService` to send tracking data to Segment.
|
||||
|
||||
:::info
|
||||
|
||||
Services can be resolved and used in Subscribers, endpoints, and other Services. Learn [how to resolve services in the Services documentation](../../development/services/create-service.md#using-your-custom-service).
|
||||
|
||||
:::
|
||||
|
||||
`track` accepts an object of data, where the keys `event` and `userId` are required. Instead of `userId`, you can use `anonymousId` to pass an anonymous user ID.
|
||||
|
||||
If you want to pass additional data to Segment, pass them under the `properties` object key.
|
||||
|
||||
The `SegmentService` also provides the method `identify` to tie a user to their actions or specific traits.
|
||||
|
||||
### Test Custom Tracking
|
||||
|
||||
After adding the above subscriber, run your backend again if it isn’t running and create a customer using the REST APIs or one of the Medusa storefronts. If you check the Debugger in your Segment source, you should see a new event “Customer Created” tracked. If you click on it, you’ll see the data you passed to the `track` method.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Services Overview](../../development/services/create-service.md)
|
||||
- [Subscribers Overview](../../development/events/create-subscriber.md)
|
||||
- [Events Reference](../../development/events/events-list.md)
|
||||
- [Deploy the Medusa backend](../../deployments/server/index.mdx)
|
||||
349
docs/content/plugins/cms/contentful/customize-contentful.md
Normal file
349
docs/content/plugins/cms/contentful/customize-contentful.md
Normal file
@@ -0,0 +1,349 @@
|
||||
---
|
||||
description: 'Learn how to customize the Contentful integration with Medusa and how to customize the Gatsby storefront that is connected to Contentful.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Customize your Medusa and Contentful Integration
|
||||
|
||||
In this document, you’ll learn how to customize the Contentful integration with Medusa and how to customize the Gatsby storefront that is connected to Contentful.
|
||||
|
||||
## Overview
|
||||
|
||||
Part of what makes the integration between Medusa and Contentful powerful is that it’s completely customizable.
|
||||
|
||||
On the backend, you can create Contentful migrations that allow you to add or edit Content Types in Contentful. Although this can be done through Contentful’s interface, this solution allows you to create a reusable codebase for your store that is independent of a specific Contentful Space.
|
||||
|
||||
On your storefront, you can add any necessary components that can render the Content Types you create.
|
||||
|
||||
As an example to explain this process, in this documentation, you’ll create a migration that creates a Rich Text content model in Contentful and edits the Page and Product content models to allow using Rich Text content as a tile in pages and products. Then, you’ll modify the Gatsby storefront to render the Rich Text content model.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
It’s assumed you already have set up a Medusa backend integrated with Contentful and have a Gatsby storefront integrated with Contentful. If not, [please follow this documentation first](index.md).
|
||||
|
||||
---
|
||||
|
||||
## Create a Contentful Migration
|
||||
|
||||
The Contentful migrations are located in the `contentful-migrations` directory in the Medusa Contentful backend starter. So, if you want to create your own Contentful migrations, you can create them under that directory.
|
||||
|
||||
Here’s an example of a migration created in a new file `contentful-migrations/rich-text.js`:
|
||||
|
||||
```jsx title=contentful-migrations/rich-text.js
|
||||
#! /usr/bin/env node
|
||||
|
||||
require("dotenv").config()
|
||||
|
||||
const { runMigration } = require("contentful-migration")
|
||||
|
||||
const options = {
|
||||
spaceId: process.env.CONTENTFUL_SPACE_ID,
|
||||
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
|
||||
environment: process.env.CONTENTFUL_ENVIRONMENT,
|
||||
yes: true,
|
||||
}
|
||||
|
||||
const migration = async () => {
|
||||
await runMigration({
|
||||
...options,
|
||||
migrationFunction: function (migration, context) {
|
||||
|
||||
// create Rich Text content model
|
||||
const richText = migration
|
||||
.createContentType("richText")
|
||||
.name("Rich Text")
|
||||
.displayField("title")
|
||||
|
||||
richText
|
||||
.createField("title")
|
||||
.name("Title (Internal)")
|
||||
.type("Symbol")
|
||||
richText
|
||||
.createField("body")
|
||||
.name("Body")
|
||||
.type("RichText")
|
||||
|
||||
// edit Page content model
|
||||
const page = migration.editContentType("page")
|
||||
|
||||
page.editField("contentModules").items({
|
||||
type: "Link",
|
||||
linkType: "Entry",
|
||||
validations: [
|
||||
{
|
||||
linkContentType: [
|
||||
"hero", "tileSection", "richText",
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
// edit Product content model
|
||||
const product = migration.editContentType("product")
|
||||
|
||||
product
|
||||
.createField("contentModules")
|
||||
.name("Content Modules")
|
||||
.type("Array")
|
||||
.items({
|
||||
type: "Link",
|
||||
linkType: "Entry",
|
||||
validations: [
|
||||
{
|
||||
linkContentType: ["richText"],
|
||||
},
|
||||
],
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
migration()
|
||||
```
|
||||
|
||||
This example creates a new content model Rich Text that has two fields: title and body. It also edits the Page content model to allow using Rich Text content models on the page.
|
||||
|
||||
In addition, it edits the Product content model by adding a new field `contentModules`. This field accepts an array of sections that can be of type Rich Text. This allows you to display rich details on a product page.
|
||||
|
||||
You can also add other types of content models the `contentModules` should accept. For example, to accept `tileSection` add it to the `linkContentType` option:
|
||||
|
||||
```jsx
|
||||
product
|
||||
.createField("contentModules")
|
||||
.name("Content Modules")
|
||||
.type("Array")
|
||||
.items({
|
||||
type: "Link",
|
||||
linkType: "Entry",
|
||||
validations: [
|
||||
{
|
||||
linkContentType: ["richText", "tileSection"],
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
### Run a Contentful Migration
|
||||
|
||||
To run a Contentful Migration that you create you can use the following command:
|
||||
|
||||
```bash
|
||||
node <file_path>
|
||||
```
|
||||
|
||||
Where `<file_path>` is the path of the file you created.
|
||||
|
||||
To run the Contentful migration in the previous example, you can use the following command:
|
||||
|
||||
```bash
|
||||
node contentful-migrations/rich-text.js
|
||||
```
|
||||
|
||||
This runs the Contentful migration in that file and makes the necessary changes in your Contentful Space.
|
||||
|
||||
### Test if Contentful Migration Worked
|
||||
|
||||
To check if the above migration worked, in your Contentful Space dashboard go to Content Models from the navigation bar. You should see the new content model Rich Text.
|
||||
|
||||

|
||||
|
||||
The above migration also allows you to add Rich Text content to pages. To test this out, go to Content from the navigation bar and choose Page in the select field next to the search bar. This shows the available pages in your Contentful Space.
|
||||
|
||||

|
||||
|
||||
Choose one of the pages. For example, the About page. Then, scroll down to the Add content button. If you click on it, you should be able to choose Rich Text under New Content.
|
||||
|
||||

|
||||
|
||||
Click on Rich Text and a new form will open to create new Rich Text content. It has the same fields that you defined in the migration file.
|
||||
|
||||

|
||||
|
||||
After adding the content you want, click on the Publish button on the right then go back to the About page editor.
|
||||
|
||||

|
||||
|
||||
Similarly, in the About page editor, click on the Publish Changes button on the right to view these changes later in the storefront.
|
||||
|
||||

|
||||
|
||||
Similarly, you can add Rich Text content to any product page.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Render New Content Models in the Storefront
|
||||
|
||||
After creating a new content model in your Contentful Space, you must add the necessary component to render it in your Gatsby storefront.
|
||||
|
||||
### Create Component
|
||||
|
||||
To render the Rich Text content you created in the previous example, create the file `src/components/rich-text/rich-text.js` with the following content:
|
||||
|
||||
```jsx title=src/components/rich-text/rich-text.js
|
||||
import React from "react"
|
||||
import {
|
||||
renderRichText,
|
||||
} from "gatsby-source-contentful/rich-text"
|
||||
|
||||
const RichText = ({ data }) => {
|
||||
return (
|
||||
<div style={{
|
||||
maxWidth: "870px",
|
||||
margin: "0 auto",
|
||||
paddingTop: "20px",
|
||||
paddingBottom: "20px",
|
||||
}}>
|
||||
{data.body ? renderRichText(data.body) : ""}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default RichText
|
||||
```
|
||||
|
||||
This creates the component `RichText` responsible for rendering the Rich Text content model. Notice that the fields of the content model are available under the `data` prop variable.
|
||||
|
||||
### Render Component in a Page
|
||||
|
||||
Since the Rich Text model can be added to any page, you must edit `src/pages/{ContentfulPage.slug}.js` to show it.
|
||||
|
||||
In `src/pages/{ContentfulPage.slug}.js`, import the `RichText` component at the top of the file:
|
||||
|
||||
```jsx title=src/pages/{ContentfulPage.slug}.js
|
||||
import RichText from "../components/rich-text/rich-text"
|
||||
```
|
||||
|
||||
Then, in the returned JSX add a new case to the switch statement:
|
||||
|
||||
```jsx title=src/pages/{ContentfulPage.slug}.js
|
||||
switch (cm.internal.type) {
|
||||
// ...
|
||||
case "ContentfulRichText":
|
||||
return <RichText key={cm.id} data={cm} />
|
||||
default:
|
||||
return null
|
||||
}
|
||||
```
|
||||
|
||||
If the content model of a tile is Rich Text, you’ll display it with the `RichText` component.
|
||||
|
||||
Finally, to retrieve all necessary data of the Rich Text content, in the `query` GraphQL variable add the following after the `... on ContentfulTileSection` fragment:
|
||||
|
||||
```jsx title=src/pages/{ContentfulPage.slug}.js
|
||||
export const query = graphql`
|
||||
# find the following line
|
||||
... on ContentfulTileSection {
|
||||
|
||||
}
|
||||
# add the following
|
||||
... on ContentfulRichText {
|
||||
id
|
||||
body {
|
||||
raw
|
||||
}
|
||||
internal {
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
```
|
||||
|
||||
### Test Rich Text in Page Content
|
||||
|
||||
To test this out, run your Medusa backend by running this command in its directory:
|
||||
|
||||
```bash
|
||||
npm run start
|
||||
```
|
||||
|
||||
Then run the Gatsby storefront by running this command in its directory:
|
||||
|
||||
```bash
|
||||
npm run start
|
||||
```
|
||||
|
||||
This runs the Gatsby storefront on `localhost:8000`. Go to the storefront in your browser and open the About page. You should see the Rich Text content you added.
|
||||
|
||||

|
||||
|
||||
### Render Component in a Product Page
|
||||
|
||||
In the example migration, you also edited the product page to include a new Content Modules field that allows inserting Rich Text content.
|
||||
|
||||
To render them on the Product Page, add the following in the GraphQL query defined in the `query` variable inside `product`:
|
||||
|
||||
```jsx title=src/pages/{ContentfulPage.slug}.js
|
||||
export const query = graphql`
|
||||
query ($id: String!) {
|
||||
product: contentfulProduct(id: { eq: $id }) {
|
||||
# Other fields
|
||||
contentModules {
|
||||
... on ContentfulRichText {
|
||||
id
|
||||
body {
|
||||
raw
|
||||
}
|
||||
internal {
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
If you added other accepted Content Models to the `contentModules` field of the Product content type, make sure to add them here.
|
||||
|
||||
:::
|
||||
|
||||
Then, in `src/views/product.js` import the `RichText` component:
|
||||
|
||||
```jsx title=src/views/product.js
|
||||
import RichText from "../components/rich-text/rich-text"
|
||||
```
|
||||
|
||||
And in the returned JSX add the following before the last `</div>`:
|
||||
|
||||
```jsx title=src/views/product.js
|
||||
<div className={styles.contentModules}>
|
||||
{product.contentModules?.map((cm) => {
|
||||
switch (cm.internal.type) {
|
||||
case "ContentfulRichText":
|
||||
return <RichText key={cm.id} data={cm} />
|
||||
default:
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
If you added other accepted Content Models to the `contentModules` field of the Product content type, make sure to add cases for them here to display them.
|
||||
|
||||
:::
|
||||
|
||||
This loops over `contentModules` and if the type of the content is Rich Text, it is rendered with the `RichText` component.
|
||||
|
||||
### Test Rich Text on a Product Page
|
||||
|
||||
Restart the Gatsby storefront then open a product that you added Rich Text content to. You should see the Rich Text component at the end of the page.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- Deploy your Medusa backend to [Heroku](../../../deployments/server/deploying-on-heroku.mdx), [Qovery](../../../deployments/server/deploying-on-qovery.md), or [DigitalOcean](../../../deployments/server/deploying-on-digital-ocean.md).
|
||||
- [How to deploy your Gatsby storefront to Netlify](../../../deployments/storefront/deploying-gatsby-on-netlify.md).
|
||||
303
docs/content/plugins/cms/contentful/index.md
Normal file
303
docs/content/plugins/cms/contentful/index.md
Normal file
@@ -0,0 +1,303 @@
|
||||
---
|
||||
description: 'Learn how to integrate Contentful with the Medusa backend and a Gatsby storefront. Contentful is a headless CMS backend that provides rich CMS functionalities.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Contentful
|
||||
|
||||
In this document, you’ll learn how to integrate a Medusa backend with Contentful to add rich Content Management System (CMS) functionalities
|
||||
|
||||
## Overview
|
||||
|
||||
[Contentful](https://www.contentful.com/) is a headless CMS service that allows developers to integrate rich CMS functionalities into any platform.
|
||||
|
||||
By integrating Contentful to Medusa, you can benefit from powerful features in your ecommerce store including detailed product CMS details, easy-to-use interface to use for static content and pages, localization, and much more.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Needed Accounts
|
||||
|
||||
- [Contentful](https://www.contentful.com/sign-up/) account with a space created. A space is created by default when you create a new account.
|
||||
|
||||
### Required Tools
|
||||
|
||||
- PostgreSQL with an empty database created. You can follow [this documentation to learn how to install it for your operating system](../../../development/backend/prepare-environment.mdx#postgres).
|
||||
- Redis. You can follow [this documentation to learn how to install it for your operating system](../../../development/backend/prepare-environment.mdx#redis).
|
||||
- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../../development/backend/prepare-environment.mdx#git).
|
||||
- Gatsby’s CLI tool. You can follow [this documentation to install it](https://www.gatsbyjs.com/docs/reference/gatsby-cli/#how-to-use-gatsby-cli).
|
||||
- Medusa’s CLI tool. You can follow [this documentation to install it](../../../cli/reference.md#how-to-install-cli-tool).
|
||||
|
||||
---
|
||||
|
||||
## Install Medusa Backend Using Contentful Starter
|
||||
|
||||
Instead of using the default Medusa backend starter, you must use the [Contentful starter](https://github.com/medusajs/medusa-starter-contentful) to install a backend that is ready to be used with Contentful. This backend contains all the necessary files to make the integration work.
|
||||
|
||||
In your terminal, run the following command to install the backend:
|
||||
|
||||
```bash
|
||||
medusa new medusa-contentful https://github.com/medusajs/medusa-starter-contentful
|
||||
```
|
||||
|
||||
This installs a new Medusa backend in the directory `medusa-contentful`.
|
||||
|
||||
### Add Contentful Environment Variables
|
||||
|
||||
Change to the `medusa-contentful` directory. In `.env` you’ll find three variables:
|
||||
|
||||
```bash title=.env
|
||||
CONTENTFUL_SPACE_ID=
|
||||
CONTENTFUL_ACCESS_TOKEN=
|
||||
CONTENTFUL_ENV=
|
||||
```
|
||||
|
||||
#### Value of CONTENTFUL_ENV
|
||||
|
||||
Set the value for `CONTENTFUL_ENV` to `master`.
|
||||
|
||||
#### Value of CONTENTFUL_SPACE_ID
|
||||
|
||||
To retrieve the value of `CONTENTFUL_SPACE_ID`, go to your [Contentful Space dashboard](https://app.contentful.com/). Then, choose Settings in the navigation bar and select API keys from the dropdown.
|
||||
|
||||

|
||||
|
||||
On the APIs page, click Add API Key.
|
||||
|
||||

|
||||
|
||||
In the form, enter a name for the API key and click Save.
|
||||
|
||||

|
||||
|
||||
Then, copy the value of Space ID and set it as the value of `CONTENTFUL_SPACE_ID`.
|
||||
|
||||
#### Value of CONTENTFUL_ACCESS_TOKEN
|
||||
|
||||
Go back to the API Keys page and click on the Content management tokens tab.
|
||||
|
||||

|
||||
|
||||
Click on Generate personal token. A pop-up will open where you have to enter a name for the token.
|
||||
|
||||

|
||||
|
||||
Once you click Generate, a personal access token will be generated. Use it to set the value of `CONTENTFUL_ACCESS_TOKEN`.
|
||||
|
||||
:::warning
|
||||
|
||||
Once you close the pop-up, you won’t be able to get the value of the personal access token again. Make sure to copy it first.
|
||||
|
||||
:::
|
||||
|
||||
### Configure Redis
|
||||
|
||||
In `.env` set the value of your Redis URL:
|
||||
|
||||
```bash
|
||||
REDIS_URL=<YOUR_REDIS_URL>
|
||||
```
|
||||
|
||||
Where `<YOUR_REDIS_URL>` is the URL of your Redis service.
|
||||
|
||||
:::tip
|
||||
|
||||
The default Redis URL is `redis://localhost:6379`.
|
||||
|
||||
:::
|
||||
|
||||
### Configure PostgreSQL
|
||||
|
||||
In `.env` set the value of your PostgreSQL URL:
|
||||
|
||||
```bash
|
||||
DATABASE_URL=<YOUR_DB_URL>
|
||||
```
|
||||
|
||||
Where `<YOUR_DB_URL>` is the URL of your PostgreSQL database.
|
||||
|
||||
:::tip
|
||||
|
||||
You can find the format of the PostgreSQL database URL in [PostgreSQL’s documentation](https://www.postgresql.org/docs/current/libpq-connect.html).
|
||||
|
||||
:::
|
||||
|
||||
Then, in `medusa-config.js` in the exported object, comment out or remove the SQLite database configurations and add the PostgreSQL database configurations:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
module.exports = {
|
||||
projectConfig: {
|
||||
// ...
|
||||
database_url: DATABASE_URL,
|
||||
database_type: "postgres",
|
||||
// REMOVE OR COMMENT OUT THE BELOW:
|
||||
// database_database: "./medusa-db.sql",
|
||||
// database_type: "sqlite",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Migrate Content Types to Contentful
|
||||
|
||||
The Contentful starter provides the necessary scripts to create content types in your Contentful space.
|
||||
|
||||
Run the following commands to migrate the content types into Contentful:
|
||||
|
||||
```bash
|
||||
npm run migrate:contentful
|
||||
```
|
||||
|
||||
Once this command finishes executing, in your Contentful Space dashboard click on Content Model in the navigation bar. You should see a list of new content models added.
|
||||
|
||||

|
||||
|
||||
### Seed Content to Contentful
|
||||
|
||||
The next step is to seed the Contentful Space with some content data.
|
||||
|
||||
Run the following command to seed some data into it:
|
||||
|
||||
```bash
|
||||
npm run seed:contentful
|
||||
```
|
||||
|
||||
After this command finishes running, in your Contentful Space dashboard click on Content in the navigation bar. You should see a list of new content added.
|
||||
|
||||

|
||||
|
||||
### (Optional) Seed Medusa Database
|
||||
|
||||
This step seeds your Medusa database with demo data to easily add products as well as other data to your Medusa backend.
|
||||
|
||||
Run the following command to seed the Medusa database:
|
||||
|
||||
```bash
|
||||
npm run seed
|
||||
```
|
||||
|
||||
### Start the Backend
|
||||
|
||||
To start the backend run the following command:
|
||||
|
||||
```bash
|
||||
npm run start
|
||||
```
|
||||
|
||||
If you seeded the database with demo data, you should see that events related to the products are triggered.
|
||||
|
||||

|
||||
|
||||
The Contentful integration ensures a two-way sync between the Medusa backend and Contentful. So, when new products are added to Medusa, these products will be added to your Contentful Space as well.
|
||||
|
||||
---
|
||||
|
||||
## (Optional) Add Products with the Medusa Admin
|
||||
|
||||
Using the Medusa admin, you can add products to your Medusa backend. This will trigger product events that subsequently add these products to Contentful.
|
||||
|
||||
---
|
||||
|
||||
## Manage Contentful Data
|
||||
|
||||
### Publish Products
|
||||
|
||||
Products added through the integration with the Medusa backend are by default saved as drafts. To show them on the storefront, you must set them as published.
|
||||
|
||||
To do that, open your Contentful Space Dashboard and click on Content in the Navigation bar. Then, change Any to Product in the select field next to the search bar. This shows only the content of the type Product, rather than all content.
|
||||
|
||||
Click on the checkbox at the top of the table to select all products then click Publish to publish these products.
|
||||
|
||||

|
||||
|
||||
### Added Featured Products
|
||||
|
||||
On the homepage of the storefront, there’s a featured products tile that shows a set of products. Before running the storefront, you must add at least one product to the list.
|
||||
|
||||
To do that, open your Contentful Space Dashboard and click on Content in the Navigation bar. Make sure the select field next to the search bar is set to Any and search for Featured Products. You should find one content of the type Tile Section.
|
||||
|
||||

|
||||
|
||||
Click on it. You should find on the page an empty Tiles section where you can add tiles and products.
|
||||
|
||||

|
||||
|
||||
Click on Add content then on Add existing content and pick some of the products you want to show on the homepage.
|
||||
|
||||

|
||||
|
||||
Once you’re done adding products, click on Publish changes in the right sidebar.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Setup Gatsby Storefront
|
||||
|
||||
In this section, you’ll set up the Gatsby storefront of your Medusa backend.
|
||||
|
||||
In your terminal in a different directory of the Medusa backend, run the following command:
|
||||
|
||||
```bash
|
||||
gatsby new medusa-contentful-storefront https://github.com/medusajs/medusa-contentful-storefront
|
||||
```
|
||||
|
||||
This will install the storefront in the directory `medusa-contentful-storefront`.
|
||||
|
||||
### Set Contentful Environment Variables
|
||||
|
||||
Change to the newly created directory and rename `.env.template`:
|
||||
|
||||
```bash
|
||||
mv .env.template .env
|
||||
```
|
||||
|
||||
Then, open `.env`. You should find the following environment variables:
|
||||
|
||||
```bash title=.env
|
||||
CONTENTFUL_SPACE_ID=
|
||||
CONTENTFUL_ACCESS_TOKEN=
|
||||
```
|
||||
|
||||
The value of `CONTENTFUL_SPACE_ID` is the same value you [retrieved while setting up the Medusa backend](#value-of-contentful_space_id).
|
||||
|
||||
To retrieve the value of `CONTENTFUL_ACCESS_TOKEN`, on your Contentful Space dashboard click on Settings then API keys. Then, choose the API key you created in the previous section.
|
||||
|
||||
You should find the field "Content Delivery API - access token”. Copy its value and set it as the value of `CONTENTFUL_ACCESS_TOKEN`.
|
||||
|
||||

|
||||
|
||||
### Start Storefront
|
||||
|
||||
Make sure the Medusa backend is still running. Then, start the storefront:
|
||||
|
||||
```bash
|
||||
npm run start
|
||||
```
|
||||
|
||||
This starts the storefront at `localhost:8000`. Open it in your browser and you should see on the homepage the Featured Product section with the products you chose on Contentful.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Make Changes to Content
|
||||
|
||||
You can update the CMS content of your storefront in your Contentful Space. This includes the CMS pages or product details.
|
||||
|
||||
:::note
|
||||
|
||||
If you make changes to the data while your Gatsby storefront is running, the changes are not reflected instantly. That’s because the data is fetched from Contentful during build time. Instead, you must restart your Gatsby storefront to see the changes you make.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## What’s Next
|
||||
|
||||
Learn [How to customize your Contentful backend and storefront](./customize-contentful.md).
|
||||
|
||||
## See Also
|
||||
|
||||
- How to deploy your Medusa backend to [Heroku](../../../deployments/server/deploying-on-heroku.mdx), [Qovery](../../../deployments/server/deploying-on-qovery.md), or [DigitalOcean](../../../deployments/server/deploying-on-digital-ocean.md).
|
||||
- [How to deploy your Gatsby storefront to Netlify](../../../deployments/storefront/deploying-gatsby-on-netlify.md).
|
||||
5
docs/content/plugins/cms/index.mdx
Normal file
5
docs/content/plugins/cms/index.mdx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# CMS Plugins
|
||||
|
||||
<DocCardList />
|
||||
199
docs/content/plugins/cms/strapi.md
Normal file
199
docs/content/plugins/cms/strapi.md
Normal file
@@ -0,0 +1,199 @@
|
||||
---
|
||||
description: 'Learn how to integrate Strapi with the Medusa backend. Learn how to install the plugin and test two-way sync between the ecommerce and CMS services.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Strapi
|
||||
|
||||
In this document, you’ll learn how to integrate Strapi with Medusa to add rich Content Management System (CMS) functionalities.
|
||||
|
||||
:::info
|
||||
|
||||
This plugin is a [community plugin](https://github.com/Deathwish98/medusa-plugin-strapi) and is not managed by the official Medusa team. At the moment, it supports v4 of Strapi.
|
||||
|
||||
:::
|
||||
|
||||
## Overview
|
||||
|
||||
[Strapi](https://strapi.io/) is an open source headless CMS service that allows developers to have complete control over their content models. It can be integrated into many other frameworks, including Medusa.
|
||||
|
||||
By integrating Strapi to Medusa, you can benefit from powerful features in your ecommerce store including detailed product CMS details, [two-way sync](#test-two-way-sync), an easy-to-use interface to use for static content and pages, and much more.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa CLI
|
||||
|
||||
[Medusa’s CLI tool](../../cli/reference.md#how-to-install-cli-tool) is required to set up a new Medusa backend.
|
||||
|
||||
### Redis
|
||||
|
||||
Redis is required for the Strapi plugin to work as expected on your Medusa backend. If you don’t have it installed, you can learn [how to install it in this documentation](../../development/backend/prepare-environment.mdx#redis).
|
||||
|
||||
---
|
||||
|
||||
## Create Strapi Project
|
||||
|
||||
The first step is to create a Strapi project using the Medusa template:
|
||||
|
||||
```bash
|
||||
npx create-strapi-app strapi-medusa --template shahednasser/strapi-medusa-template
|
||||
```
|
||||
|
||||
This creates the Strapi project in the directory `strapi-medusa`.
|
||||
|
||||
Once the installation is finished, the Strapi development backend will run on `localhost:1337`. A new page will also open in your default browser to create a new admin user and log in.
|
||||
|
||||

|
||||
|
||||
Once you log in, you can access the Strapi dashboard.
|
||||
|
||||
### Create a Strapi User
|
||||
|
||||
The Strapi plugin in Medusa requires the credentials of a Strapi user. To create a new user, go to Content Manager, then choose User under Collection Types.
|
||||
|
||||

|
||||
|
||||
Click on the Create new entry button at the top right. This opens a new form to enter the user’s details.
|
||||
|
||||

|
||||
|
||||
Enter the user’s username, email, and password. Once you’re done, click on the Save button at the top right.
|
||||
|
||||
---
|
||||
|
||||
## Modify Permissions
|
||||
|
||||
By default, created users have the “Authenticated” role. Before you start using the Strapi plugin on your Medusa backend, you must modify this role’s permissions to allow making changes to Medusa’s models in Strapi.
|
||||
|
||||
On your Strapi dashboard, go to Settings → Roles → Authenticated. Then, under the Permissions section, expand the accordion of each content model type and check the Select All checkbox.
|
||||
|
||||

|
||||
|
||||
Once you’re done, click the Save button at the top right.
|
||||
|
||||
---
|
||||
|
||||
## Create Medusa Backend
|
||||
|
||||
:::note
|
||||
|
||||
You can use the Strapi plugin on an existing Medusa backend, however, existing data (such as existing products) will not be imported. Only newer data will be imported.
|
||||
|
||||
:::
|
||||
|
||||
To create your Medusa backend, run the following command:
|
||||
|
||||
```bash
|
||||
medusa new medusa-backend --seed
|
||||
```
|
||||
|
||||
The `--seed` flag creates an SQLite database and seeds it with some demo data.
|
||||
|
||||
### Configure your Backend
|
||||
|
||||
Once the command is done executing, change to the newly created `medusa-backend` directory. Then, in `medusa-config.js`, change the exported object at the end of the file to enable Redis:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
module.exports = {
|
||||
projectConfig: {
|
||||
redis_url: REDIS_URL,
|
||||
// ...
|
||||
},
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
This uses the default Redis configurations. If you want to learn more about configuring Redis, [check out this documentation](../../development/backend/configurations.md#redis).
|
||||
|
||||
:::tip
|
||||
|
||||
It is also recommended to use PostgreSQL for an optimal experience, however, it is not required. Learn how to [install](../../development/backend/prepare-environment.mdx#postgres) and [configure](../../development/backend/configurations.md#postgresql-configurations) it on your Medusa backend.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Install the Strapi Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the Strapi plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-strapi
|
||||
```
|
||||
|
||||
Then, add the following environment variables:
|
||||
|
||||
```bash
|
||||
STRAPI_USER=<STRAPI_IDENTIFIER>
|
||||
STRAPI_PASSWORD=<STRAPI_PASSWORD>
|
||||
STRAPI_PROTOCOL=http # Optional
|
||||
STRAPI_URL=<STRAPI_URL> # Optional
|
||||
STRAPI_PORT=<STRAPI_PORT> # Optional
|
||||
```
|
||||
|
||||
Where:
|
||||
|
||||
- `<STRAPI_IDENTIFIER>` is either the email address or username of the user you created in the previous step.
|
||||
- `<STRAPI_PASSWORD>` is the password of the user you created in the previous step.
|
||||
- `<STRAPI_PROTOCOL>` is the protocol of your Strapi backend. If you’re using a local Strapi backend, set this to `http`. The default value is `https`.
|
||||
- `<STRAPI_URL>` is the URL of your Strapi backend. By default, the URL is `localhost`.
|
||||
- `<STRAPI_PORT>` is the port the Strapi backend runs on. By default, the port is `1337`.
|
||||
|
||||
Finally, open `medusa-config.js` and add the following new item to the `plugins` array:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-plugin-strapi`,
|
||||
options: {
|
||||
strapi_medusa_user: process.env.STRAPI_USER,
|
||||
strapi_medusa_password: process.env.STRAPI_PASSWORD,
|
||||
strapi_url: process.env.STRAPI_URL, // optional
|
||||
strapi_port: process.env.STRAPI_PORT, // optional
|
||||
strapi_protocol: process.env.STRAPI_PROTOCOL, // optional
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Run Medusa Backend
|
||||
|
||||
Make sure the Strapi backend is still running. If not, you can run the following command to run the Strapi backend in the directory of the Strapi project:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run develop
|
||||
```
|
||||
|
||||
Then, in the directory of your Medusa backend, run the following command to start the Medusa backend:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run start
|
||||
```
|
||||
|
||||
Once you start your Medusa backend, if you ran the `--seed` command when you created your Medusa backend, you’ll see that `product.created` events have been triggered along with similar events. This will update Strapi with the products you seeded.
|
||||
|
||||
---
|
||||
|
||||
## Test Two-Way Sync
|
||||
|
||||
This plugin ensures a two-way sync between the Medusa backend and the Strapi backend. So, if you update data on Strapi, it will be reflected on your Medusa backend, and vice-versa.
|
||||
|
||||
### Update Products on Strapi
|
||||
|
||||
Try updating any products on Strapi by going to Content Manager → Products and choosing a product from the list. Then, make changes to the product and click Save. If you view the products on your backend now, either using the [REST APIs](/api/admin/#tag/Product/operation/GetProducts) or using [the Medusa Admin](../../user-guide/products/index.mdx), you’ll see that the product has been updated.
|
||||
|
||||
### Update Products on Medusa
|
||||
|
||||
If you try to update products on Medusa either using the [REST APIs](/api/admin/#tag/Product/operation/PostProductsProduct) or using [the Medusa Admin](../../user-guide/products/manage.mdx), you’ll see that the product is also updated on Strapi.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Deploy the Medusa backend](../../deployments/server/index.mdx)
|
||||
- [Create your own plugin](../../development/plugins/create.md)
|
||||
5
docs/content/plugins/file-service/index.mdx
Normal file
5
docs/content/plugins/file-service/index.mdx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# File Service Plugins
|
||||
|
||||
<DocCardList />
|
||||
226
docs/content/plugins/file-service/minio.md
Normal file
226
docs/content/plugins/file-service/minio.md
Normal file
@@ -0,0 +1,226 @@
|
||||
---
|
||||
description: 'Learn how to integrate MinIO with the Medusa backend. Learn how to install the MinIO plugin on the Medusa backend and configure it.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# MinIO
|
||||
|
||||
This document will guide you through installing the MinIO file service plugin on your Medusa backend.
|
||||
|
||||
## Overview
|
||||
|
||||
To manage images in Medusa, you need a file service plugin responsible for hosting. Without a file service plugin, you will face issues while working with Medusa, such as when uploading images for products.
|
||||
|
||||
Medusa provides three different options to handle your file storage. This document will focus on setting up [MinIO](https://min.io) on your local machine and connecting Medusa to it.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
A Medusa backend is required to be set up before following along with this document. You can follow the [quickstart guide](../../development/backend/install.mdx) to get started in minutes.
|
||||
|
||||
---
|
||||
|
||||
## Set up MinIO
|
||||
|
||||
You can follow [MinIO’s guide to install it](https://docs.min.io/minio/baremetal/quickstart/quickstart.html) on your machine based on your operating system.
|
||||
|
||||
After installing it, make sure MinIO is always running when your Medusa backend is running. It’s recommended that you set up an alias to quickly start the MinIO backend as instructed at the end of the installation guides in MinIO.
|
||||
|
||||
### Change MinIO port
|
||||
|
||||
In MinIO’s documentation, port `9000` is used for the address of the MinIO backend. However, this collides with the port for the Medusa backend. You must change the port for MinIO to another one (for example, port `9001`).
|
||||
|
||||
After setting up and installing MinIO on your system/sub-system, you can run the following command to change MinIO port to `9001` (or any other available port) instead of `9000` to avoid the port clash:
|
||||
|
||||
```bash
|
||||
minio backend ~/minio --console-address :9090 --address :9001
|
||||
```
|
||||
|
||||
### Create a MinIO bucket
|
||||
|
||||
After installing MinIO and logging into the Console, you can create a bucket that will store the files of your Medusa backend by following these steps:
|
||||
|
||||
1. Click on the “Create Bucket” button
|
||||
2. For the Bucket Name field, enter a name for the bucket. By MinIO’s requirement, the name can only consist of lower case characters, numbers, dots (`.`), and hyphens (`-`).
|
||||
3. Click on the Create Bucket button.
|
||||
4. On the bucket's page, click on the cog icon at the top right to configure the bucket.
|
||||
5. Click on the edit icon next to Access Policy.
|
||||
6. In the pop-up that opens, change the selected value to “public” and click Set.
|
||||
|
||||
:::warning
|
||||
|
||||
Changing the Access Policy to public will allow anyone to access your bucket. Avoid storing sensitive data in the bucket.
|
||||
|
||||
:::
|
||||
|
||||
### Generate Access Keys
|
||||
|
||||
To generate access keys for your plugin:
|
||||
|
||||
1. From the sidebar of your MinIO console, click on Access Keys
|
||||
2. Click on the "Create access key" button
|
||||
3. This will open a new form with randomly-generated keys. Click on the Create button.
|
||||
4. A pop-up will then show the value for your Access Key and Secret Key. Copy them to use in the next section.
|
||||
|
||||
:::caution
|
||||
|
||||
You will not be able to access the Secret Key after closing the pop-up. So, make sure to store it somewhere to use later when configuring the plugin.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Plugin Installation
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the MinIO plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-file-minio
|
||||
```
|
||||
|
||||
Then, add the following environment variables in `.env`:
|
||||
|
||||
```bash
|
||||
MINIO_ENDPOINT=<ENDPOINT>
|
||||
MINIO_BUCKET=<BUCKET>
|
||||
MINIO_ACCESS_KEY=<ACCESS_KEY>
|
||||
MINIO_SECRET_KEY=<SECRET_KEY>
|
||||
```
|
||||
|
||||
Where `<ENDPOINT>` is the URL of your MinIO backend, `<BUCKET>` is the name of the bucket you created earlier, and `<ACCESS_KEY>` and `<SECRET_KEY>` are the keys you generated in the previous section.
|
||||
|
||||
Finally, configure your `medusa-config.js` to include the plugin with the required options:
|
||||
|
||||
```js title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-file-minio`,
|
||||
options: {
|
||||
endpoint: process.env.MINIO_ENDPOINT,
|
||||
bucket: process.env.MINIO_BUCKET,
|
||||
access_key_id: process.env.MINIO_ACCESS_KEY,
|
||||
secret_access_key: process.env.MINIO_SECRET_KEY,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
:::caution
|
||||
|
||||
If you have multiple storage plugins configured, the last plugin declared in the `medusa-config.js` file will be used.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Test it Out
|
||||
|
||||
Run your Medusa backend alongside the [Medusa Admin](../../admin/quickstart.mdx) to try out your new file service. Upon editing or creating products, you can now upload thumbnails and images, that are stored in a MinIO backend.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Private Buckets
|
||||
|
||||
### Handle Exports
|
||||
|
||||
Medusa provides export functionalities including exporting products and orders. For exports to work, you must [set up a private bucket](#create-private-bucket).
|
||||
|
||||
### Handle Imports
|
||||
|
||||
Medusa provides import functionalities including importing products. For imports to work, you must [set the private bucket](#add-private-bucket-environment-variable) to be the same as the public bucket.
|
||||
|
||||
### Create Private Bucket
|
||||
|
||||
To create a private bucket, follow along the [steps mentioned earlier](#create-a-minio-bucket), but keep Access Policy set to private.
|
||||
|
||||
### Add Private Bucket Environment Variable
|
||||
|
||||
Add the following environment variable on your Medusa backend:
|
||||
|
||||
```bash
|
||||
MINIO_PRIVATE_BUCKET=exports
|
||||
```
|
||||
|
||||
Then, add a new option to the plugin’s options in `medusa-config.js`:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-file-minio`,
|
||||
options: {
|
||||
// ...
|
||||
private_bucket: process.env.MINIO_PRIVATE_BUCKET,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
### Use Different Secret and Access Keys
|
||||
|
||||
If you only add the `private_bucket` option, the same secret and access keys that you used for the public bucket will be used to access the private bucket.
|
||||
|
||||
If you want to use different keys, set the following environment variables:
|
||||
|
||||
```bash
|
||||
MINIO_PRIVATE_ACCESS_KEY=<YOUR_PRIVATE_ACCESS_KEY>
|
||||
MINIO_PRIVATE_SECRET_KEY=<YOUR_PRIVATE_SECRET_KEY>
|
||||
```
|
||||
|
||||
Where `<YOUR_PRIVATE_ACCESS_KEY>` and `<YOUR_PRIVATE_SECRET_KEY>` are the access key and secret access key that have access to the private MinIO bucket.
|
||||
|
||||
Then, add two new options to the plugin’s options in `medusa-config.js`:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-file-minio`,
|
||||
options: {
|
||||
// ...
|
||||
private_access_key_id:
|
||||
process.env.MINIO_PRIVATE_ACCESS_KEY,
|
||||
private_secret_access_key:
|
||||
process.env.MINIO_PRIVATE_SECRET_KEY,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next.js Storefront Configuration
|
||||
|
||||
If you’re using a [Next.js](../../starters/nextjs-medusa-starter.mdx) storefront, you need to add an additional configuration that adds the MinIO domain name into the configured images domain names. This is because all URLs of product images will be from the MinIO backend.
|
||||
|
||||
If this configuration is not added, you’ll receive the error ["next/image Un-configured Host”](https://nextjs.org/docs/messages/next-image-unconfigured-host).
|
||||
|
||||
In `next.config.js` add the following option in the exported object:
|
||||
|
||||
```jsx title=next.config.js
|
||||
const { withStoreConfig } = require("./store-config")
|
||||
|
||||
// ...
|
||||
|
||||
module.exports = withStoreConfig({
|
||||
// ...
|
||||
images: {
|
||||
domains: [
|
||||
// ...
|
||||
"127.0.0.1",
|
||||
],
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Where `127.0.0.1` is the domain of your local MinIO backend.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- Check out [more plugins](../overview.mdx) you can add to your store.
|
||||
227
docs/content/plugins/file-service/s3.md
Normal file
227
docs/content/plugins/file-service/s3.md
Normal file
@@ -0,0 +1,227 @@
|
||||
---
|
||||
description: 'Learn how to integrate the S3 plugin with the Medusa backend. Learn how to configure and use S3 to store images related to the Medusa backend.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# S3
|
||||
|
||||
In this document, you’ll learn how to install the [S3 plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-file-s3) on your Medusa backend and use it for storage.
|
||||
|
||||
## Overview
|
||||
|
||||
To manage images in Medusa, you need a file service plugin responsible for hosting the images. Without a file service plugin, you will face issues while working with Medusa, such as when uploading images for products.
|
||||
|
||||
Medusa provides three different options to handle your file storage. This document focuses on using [S3](https://aws.amazon.com/s3/) to store images and files uploaded to the Medusa backend.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Backend
|
||||
|
||||
A Medusa backend is required to be set up before following along with this document. You can follow the [quickstart guide](../../development/backend/install.mdx) to get started in minutes.
|
||||
|
||||
### Required Accounts
|
||||
|
||||
You need to [create an AWS account](https://console.aws.amazon.com/console/home?nc2=h_ct&src=header-signin) to follow along with this documentation.
|
||||
|
||||
---
|
||||
|
||||
## Create S3 Bucket
|
||||
|
||||
On your AWS Console, search for S3 in the search box at the top. Then, choose the first result you see which should be S3 under the Services category.
|
||||
|
||||

|
||||
|
||||
Then, on the new page that opens, click on Create Bucket button at the top right of the Buckets table.
|
||||
|
||||

|
||||
|
||||
The Create Bucket form will open. In the General Configuration section enter a name for the bucket and choose a region for the bucket. Both of the values of these fields are important as you’ll use them throughout the documentation.
|
||||
|
||||

|
||||
|
||||
Next, in the Object Ownership section, choose ACLs enabled. Then, two radio buttons will show below it. Choose Bucket owner preferred.
|
||||
|
||||

|
||||
|
||||
Then, in the “Block Public Access settings for this bucket” section, uncheck the “Block all public access” checkbox. This shows a warning message at the bottom of the section with another checkbox. Check the checkbox to ensure you understand that objects in the bucket are publicly accessible.
|
||||
|
||||

|
||||
|
||||
You can leave the rest of the fields in the form as is and scroll down to the end of the page. Then, click on the Create Bucket button.
|
||||
|
||||
---
|
||||
|
||||
## Manage Bucket Policies
|
||||
|
||||
On the page of the bucket you just created, click on the Permissions tab. Then, scroll down until you find the Bucket policy section. Click on Edit in that section.
|
||||
|
||||

|
||||
|
||||
In the Edit Bucket Policy page, enter the following in the field:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Id": "Policy1397632521960",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Stmt1397633323327",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": "s3:GetObject",
|
||||
"Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to replace `<YOUR_BUCKET_NAME>` with the name of the bucket you created.
|
||||
|
||||
Once you’re done, scroll down and click on the Save changes button.
|
||||
|
||||
### User Permissions
|
||||
|
||||
Your user must have the `AmazonS3FullAccess` policy attached to it. You can refer to [this guide](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-and-attach-iam-policy.html) to learn how to add a policy if necessary.
|
||||
|
||||
### Obtain Access Keys
|
||||
|
||||
You must obtain access keys for your user as you’ll use them to integrate the S3 plugin in Medusa with your bucket. To obtain the Access Key ID and the Secret Access Key, check out [this guide](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
|
||||
|
||||
---
|
||||
|
||||
## Install the S3 Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the S3 Plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-file-s3
|
||||
```
|
||||
|
||||
Then, add the following environment variables:
|
||||
|
||||
```bash
|
||||
S3_URL=<YOUR_BUCKET_URL>
|
||||
S3_BUCKET=<YOUR_BUCKET_NAME>
|
||||
S3_REGION=<YOUR_BUCKET_REGION>
|
||||
S3_ACCESS_KEY_ID=<YOUR_ACCESS_KEY_ID>
|
||||
S3_SECRET_ACCESS_KEY=<YOUR_SECRET_ACCESS_KEY>
|
||||
```
|
||||
|
||||
Where:
|
||||
|
||||
1. `<YOUR_BUCKET_URL>` is the URL to your bucket. It’s in the form `https://<BUCKET_NAME>.s3.<REGION>.amazonaws.com`, where `<BUCKET_NAME>` is the name of the bucket and the `<REGION>` is the region the bucket is created in. If you’re not sure which region, on your bucket’s page on S3 click on Properties. You can then find the region under AWS Region. Make sure to only copy the code (for example, `us-east-1`).
|
||||
2. `<YOUR_BUCKET_NAME>` is the name of the bucket you created.
|
||||
3. `<YOUR_BUCKET_REGION>` is the region code of your bucket. For example, `us-east-1`.
|
||||
4. `<YOUR_ACCESS_KEY_ID>` is the Access Key ID that you created for your user.
|
||||
5. `<YOUR_SECRET_ACCESS_KEY>` is the Secret Access Key that you created for your user.
|
||||
|
||||
Finally, in `medusa-config.js`, add to the `plugins` array the following new item:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-file-s3`,
|
||||
options: {
|
||||
s3_url: process.env.S3_URL,
|
||||
bucket: process.env.S3_BUCKET,
|
||||
region: process.env.S3_REGION,
|
||||
access_key_id: process.env.S3_ACCESS_KEY_ID,
|
||||
secret_access_key: process.env.S3_SECRET_ACCESS_KEY,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
### Add AWS Configurations
|
||||
|
||||
You can pass AWS configurations in the plugin's options under the property `aws_config_object`. This property is an object that accepts [AWS Configurations](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html) as its properties.
|
||||
|
||||
For example, you can pass the `region`, `access_key_id` and `secret_access_key` in `aws_config_object`:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-file-s3`,
|
||||
options: {
|
||||
s3_url: process.env.S3_URL,
|
||||
bucket: process.env.S3_BUCKET,
|
||||
aws_config_object: {
|
||||
region: process.env.S3_REGION,
|
||||
access_key_id: process.env.S3_ACCESS_KEY_ID,
|
||||
secret_access_key: process.env.S3_SECRET_ACCESS_KEY,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
Make sure to define `S3_REGION`, `S3_ACCESS_KEY_ID`, and `S3_SECRET_ACCESS_KEY` in your environment variables first.
|
||||
|
||||
|
||||
:::caution
|
||||
|
||||
If you have multiple storage plugins configured, the last plugin declared in the `medusa-config.js` file will be used.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Test the S3 Plugin
|
||||
|
||||
Run your Medusa backend with the following command:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run start
|
||||
```
|
||||
|
||||
Then, you can either test the plugin using the [REST APIs](/api/store) or using the [Medusa Admin](../../admin/quickstart.mdx).
|
||||
|
||||
On the Medusa Admin, create a new product and, in the Images section, upload an image then click Save. If the integration was successful, the product image will be uploaded successfully.
|
||||
|
||||

|
||||
|
||||
You can also check that the image was uploaded on the S3 bucket’s page.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Next.js Storefront Configuration
|
||||
|
||||
If you’re using a [Next.js](../../starters/nextjs-medusa-starter.mdx) storefront, you need to add an additional configuration that adds the S3 bucket domain name into the configured images’ domain names. This is because all URLs of product images will be from the S3 bucket.
|
||||
|
||||
If this configuration is not added, you’ll receive the error ["next/image Un-configured Host”](https://nextjs.org/docs/messages/next-image-unconfigured-host).
|
||||
|
||||
In `next.config.js` add the following option in the exported object:
|
||||
|
||||
```jsx title=next.config.js
|
||||
const { withStoreConfig } = require("./store-config")
|
||||
|
||||
// ...
|
||||
|
||||
module.exports = withStoreConfig({
|
||||
// ...
|
||||
images: {
|
||||
domains: [
|
||||
// ...
|
||||
"<BUCKET_NAME>.s3.amazonaws.com",
|
||||
],
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Where `<BUCKET_NAME>` is the name of the S3 bucket you’re using.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- Check out [more plugins](../overview.mdx) you can add to your store.
|
||||
- [Deploy the Medusa backend](../../deployments/server/index.mdx)
|
||||
- Install the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts.
|
||||
187
docs/content/plugins/file-service/spaces.md
Normal file
187
docs/content/plugins/file-service/spaces.md
Normal file
@@ -0,0 +1,187 @@
|
||||
---
|
||||
description: 'Learn how to integrate Spaces with the Medusa backend. Learn how to install and configure the Spaces plugin on the Medusa backend.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Spaces
|
||||
|
||||
In this document, you’ll learn how to install the [Spaces plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-file-spaces) on your Medusa backend and use it for storage.
|
||||
|
||||
<div>
|
||||
<video width="100%" height="100%" playsinline autoplay muted controls>
|
||||
<source src="https://user-images.githubusercontent.com/59018053/154808767-7c030254-1879-41fd-a71c-b31c5508d8a4.mp4" type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
To manage images in Medusa, you need a file service plugin responsible for hosting the images. Without a file service plugin, you will face issues while working with Medusa, such as when uploading images for products.
|
||||
|
||||
Medusa provides three different options to handle your file storage. This document focuses on using [Spaces](https://www.digitalocean.com/products/spaces) to store images and files uploaded to the Medusa backend.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Backend
|
||||
|
||||
A Medusa backend is required to be set up before following along with this document. You can follow the [quickstart guide](../../development/backend/install.mdx) to get started in minutes.
|
||||
|
||||
### Required Accounts
|
||||
|
||||
You need to [create a DigitalOcean account](https://cloud.digitalocean.com/registrations/new) to follow along with this documentation. A credit card is required during registration.
|
||||
|
||||
---
|
||||
|
||||
## Create DigitalOcean Space
|
||||
|
||||
In your DigitalOcean account, click on the Create button at the top right, then choose Spaces from the dropdown.
|
||||
|
||||

|
||||
|
||||
In the Create a Space form, you can choose any of the regions listed. You can alternatively leave all settings as they are and scroll down to the Finalize and Create section.
|
||||
|
||||

|
||||
|
||||
In the Finalize and Create section, enter a name for the field “Choose a unique name”. You’ll use this name later in the integration with Medusa. Also, select the project you want to add the new Space to.
|
||||
|
||||

|
||||
|
||||
Once you’re done, click on the Create a Space button. This creates the Space and redirects you to the Space’s page.
|
||||
|
||||
---
|
||||
|
||||
## Create Space Access Keys
|
||||
|
||||
Choose API from the bottom of the sidebar.
|
||||
|
||||

|
||||
|
||||
This opens the Application & API page. Scroll down to Spaces Access Keys and click the Generate New Key button.
|
||||
|
||||

|
||||
|
||||
This shows a table with the Name field editable. Enter a name for the Access Keys and click on the checkmark button to save and generate the Spaces access keys.
|
||||
|
||||

|
||||
|
||||
Then, two keys will be available under the Key column of the table. The first one is the Access Key ID and the second is the Secret Access Key. Copy both as you’ll use them later.
|
||||
|
||||
:::caution
|
||||
|
||||
The secret access key will not be shown again after you leave the page. Make sure to copy it when you see it or you’ll need to re-generate a new one.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Install the Spaces Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the Spaces plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-file-spaces
|
||||
```
|
||||
|
||||
Then, add the following environment variables:
|
||||
|
||||
```bash
|
||||
SPACE_URL=<YOUR_SPACE_URL>
|
||||
SPACE_BUCKET=<YOUR_SPACE_NAME>
|
||||
SPACE_ENDPOINT=<YOUR_SPACE_ENDPOINT>
|
||||
SPACE_ACCESS_KEY_ID=<YOUR_ACCESS_KEY_ID>
|
||||
SPACE_SECRET_ACCESS_KEY=<YOUR_SECRET_ACCESS_KEY>
|
||||
```
|
||||
|
||||
Where:
|
||||
|
||||
1. `<YOUR_SPACE_URL>` is the URL of your Space which you can find on the Space’s page below the Space’s name.
|
||||
|
||||

|
||||
|
||||
2. `<YOUR_SPACE_NAME>` is the name of your Space.
|
||||
3. `<YOUR_SPACE_ENDPOINT>` is your Space’s endpoint which can be found by going to your Space’s page, clicking on the Settings tab, and scrolling to the Endpoint section.
|
||||
|
||||

|
||||
|
||||
4. `<YOUR_ACCESS_KEY_ID>` and `<YOUR_SECRET_ACCESS_KEY>` are the keys you created in the previous section.
|
||||
|
||||
Finally, in `medusa-config.js` add a new item to the `plugins` array:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-file-spaces`,
|
||||
options: {
|
||||
spaces_url: process.env.SPACE_URL,
|
||||
bucket: process.env.SPACE_BUCKET,
|
||||
endpoint: process.env.SPACE_ENDPOINT,
|
||||
access_key_id: process.env.SPACE_ACCESS_KEY_ID,
|
||||
secret_access_key: process.env.SPACE_SECRET_ACCESS_KEY,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
:::caution
|
||||
|
||||
If you have multiple storage plugins configured, the last plugin declared in the `medusa-config.js` file will be used.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Test the Space Plugin
|
||||
|
||||
Run your Medusa backend with the following command:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run start
|
||||
```
|
||||
|
||||
Then, you can either test the plugin using the [REST APIs](/api/store) or using the [Medusa Admin](../../admin/quickstart.mdx).
|
||||
|
||||
On the Medusa Admin, create a new product and, in the Images section, upload an image then click Save. If the integration was successful, the product image will be uploaded successfully.
|
||||
|
||||

|
||||
|
||||
You can also check that the image was uploaded on the Space’s page.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Next.js Storefront Configuration
|
||||
|
||||
If you’re using a [Next.js](../../starters/nextjs-medusa-starter.mdx) storefront, you need to add an additional configuration that adds the Space’s domain name into the configured images’ domain names. This is because all URLs of product images will be from the Space.
|
||||
|
||||
If this configuration is not added, you’ll receive the error ["next/image Un-configured Host”](https://nextjs.org/docs/messages/next-image-unconfigured-host).
|
||||
|
||||
In `next.config.js` add the following option in the exported object:
|
||||
|
||||
```jsx title=next.config.js
|
||||
const { withStoreConfig } = require("./store-config")
|
||||
|
||||
// ...
|
||||
|
||||
module.exports = withStoreConfig({
|
||||
// ...
|
||||
images: {
|
||||
domains: [
|
||||
// ...
|
||||
"<YOUR_SPACE_DOMAIN>",
|
||||
],
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Where `<YOUR_SPACE_DOMAIN>` is the domain name for your Space which can be retrieved from the Space URL. For example, `medusa-backend.digitaloceanspaces.com`.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- Check out [more plugins](../overview.mdx) you can add to your store.
|
||||
- [Deploy the Medusa backend on DigitalOcean](../../deployments/server/deploying-on-digital-ocean.md).
|
||||
- Install the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefront.
|
||||
5
docs/content/plugins/notifications/index.mdx
Normal file
5
docs/content/plugins/notifications/index.mdx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Notifications Plugins
|
||||
|
||||
<DocCardList />
|
||||
209
docs/content/plugins/notifications/mailchimp.md
Normal file
209
docs/content/plugins/notifications/mailchimp.md
Normal file
@@ -0,0 +1,209 @@
|
||||
---
|
||||
description: 'Learn how to integrate Mailchimp with the Medusa backend. Learn how to install the plugin on the Medusa backend and how to add a subscription form.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Mailchimp
|
||||
|
||||
In this document, you’ll learn about the Mailchimp plugin, what it does, and how to use it.
|
||||
|
||||
## Overview
|
||||
|
||||
[Mailchimp](https://mailchimp.com) is an email marketing service that can be used to create newsletters and subscriptions.
|
||||
|
||||
By integrating Mailchimp with Medusa, customers will be able to subscribe from Medusa to your Mailchimp newsletter and will be automatically added to your Mailchimp subscribers list.
|
||||
|
||||
:::note
|
||||
|
||||
This plugin is only used to allow your customers to subscribe but does not actually do any email sending. If you want to send emails to customers based on specific events, for example, when an order is placed, you should check out the [SendGrid plugin](./sendgrid.mdx) instead.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before going further with this guide make sure you have a Medusa backend set up. You can follow the [Quickstart guide](../../development/backend/install.mdx).
|
||||
|
||||
You also need a Mailchimp account, so please [create one](https://mailchimp.com/signup) before you start.
|
||||
|
||||
---
|
||||
|
||||
## Obtain Mailchimp Keys
|
||||
|
||||
To integrate the plugin into Medusa you need two keys: The API Key and the Newsletter list or Audience ID. The API Key acts as a credential for your account, whereas the Newsletter list ID determines which audience should the subscribed customers be added to.
|
||||
|
||||
You can follow [this guide](https://mailchimp.com/help/about-api-keys/#Find_or_generate_your_API_key) from Mailchimp’s documentation to obtain an API Key.
|
||||
|
||||
You can follow [this guide](https://mailchimp.com/help/find-audience-id/) from Mailchimp’s documentation to obtain your Newsletter list or Audience ID.
|
||||
|
||||
---
|
||||
|
||||
## Install the Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the Mailchimp plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-mailchimp
|
||||
```
|
||||
|
||||
### Add Keys
|
||||
|
||||
Open `.env` and add the following keys:
|
||||
|
||||
```bash
|
||||
MAILCHIMP_API_KEY=<YOUR_API_KEY>
|
||||
MAILCHIMP_NEWSLETTER_LIST_ID=<YOUR_NEWSLETTER_LIST_ID>
|
||||
```
|
||||
|
||||
Make sure to replace `<YOUR_API_KEY>` with your API Key and `<YOUR_NEWSLETTER_LIST_ID>` with your Newsletter list or Audience ID.
|
||||
|
||||
### Add Plugin to Medusa Config
|
||||
|
||||
Open `medusa-config.js` and add the new plugin into the `plugins` array:
|
||||
|
||||
```js title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...,
|
||||
{
|
||||
resolve: `medusa-plugin-mailchimp`,
|
||||
options: {
|
||||
api_key: process.env.MAILCHIMP_API_KEY,
|
||||
newsletter_list_id:
|
||||
process.env.MAILCHIMP_NEWSLETTER_LIST_ID,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test it Out
|
||||
|
||||
This plugin adds a new `POST` endpoint at `/mailchimp/subscribe`. This endpoint requires in the body of the request an `email` field. You can also optionally include a `data` object that holds any additional data you want to send to Mailchimp. You can check out [Mailchimp’s subscription documentation](https://mailchimp.com/developer/marketing/api/list-members/add-member-to-list/) for more details on the data you can send.
|
||||
|
||||
### Without Additional Data
|
||||
|
||||
Try sending a `POST` request to `/mailchimp/subscribe` with the following JSON body:
|
||||
|
||||
```json noReport
|
||||
{
|
||||
"email": "example@gmail.com"
|
||||
}
|
||||
```
|
||||
|
||||
If the subscription is successful, a `200` response code will be returned with `OK` message.
|
||||
|
||||

|
||||
|
||||
If you check your Mailchimp dashboard, you should find the email added to your Audience list.
|
||||
|
||||

|
||||
|
||||
### With Additional Data
|
||||
|
||||
Here’s an example of sending additional data with the subscription:
|
||||
|
||||
```json noReport
|
||||
{
|
||||
"email": "example@gmail.com",
|
||||
"data": {
|
||||
"tags": ["customer"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
All fields inside `data` will be sent to Mailchimp’s API along with the email.
|
||||
|
||||
---
|
||||
|
||||
## Use Mailchimp Service
|
||||
|
||||
If you want to subscribe to users without using this endpoint or at a specific place in your code, you can use Mailchimp’s service `mailchimpService` in your endpoints, services, or subscribers. This service has a method `subscribeNewsletter` which lets you use the subscribe functionality.
|
||||
|
||||
Here’s an example of using the `mailchimpService` inside an endpoint:
|
||||
|
||||
```jsx title=src/api/index.ts
|
||||
const mailchimpService = req.scope.resolve("mailchimpService")
|
||||
|
||||
mailchimpService.subscribeNewsletter(
|
||||
"example@gmail.com",
|
||||
{ tags: ["customer"] } // optional
|
||||
)
|
||||
```
|
||||
|
||||
:::tip
|
||||
|
||||
You can learn more about how you can use services in your endpoints, services, and subscribers in the [Services documentation](../../development/services/create-service.md#using-your-custom-service).
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Add Subscription Form
|
||||
|
||||
This section has a simple example of adding a subscription form in your storefront. The code is for React-based frameworks but you can use the same logic for your storefronts regardless of the framework you are using.
|
||||
|
||||
You’ll need to use [axios](https://github.com/axios/axios) to send API requests, so if you don’t have it installed make sure you install it first:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install axios
|
||||
```
|
||||
|
||||
Then, in the component you want to add the subscription form add the following code:
|
||||
|
||||
```tsx
|
||||
import axios from "axios"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function NewsletterForm() {
|
||||
const [email, setEmail] = useState("")
|
||||
|
||||
function subscribe(e) {
|
||||
e.preventDefault()
|
||||
if (!email) {
|
||||
return
|
||||
}
|
||||
|
||||
axios.post("http://localhost:9000/mailchimp/subscribe", {
|
||||
email,
|
||||
})
|
||||
.then((e) => {
|
||||
alert("Subscribed sucessfully!")
|
||||
setEmail("")
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e)
|
||||
alert("An error occurred")
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={subscribe}>
|
||||
<h2>Sign Up for our newsletter</h2>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
placeholder="example@gmail.com"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
<button type="submit">Subscribe</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
This will result in a subscription form similar to the following:
|
||||
|
||||

|
||||
|
||||
If you try entering an email and clicking Subscribe, the email will be subscribed to your Mailchimp newsletter successfully.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- Check out [SendGrid plugin](./sendgrid.mdx) for more Email functionalities.
|
||||
- [Plugins Overview](../../development/plugins/overview.mdx)
|
||||
3987
docs/content/plugins/notifications/sendgrid.mdx
Normal file
3987
docs/content/plugins/notifications/sendgrid.mdx
Normal file
File diff suppressed because it is too large
Load Diff
114
docs/content/plugins/notifications/slack.md
Normal file
114
docs/content/plugins/notifications/slack.md
Normal file
@@ -0,0 +1,114 @@
|
||||
---
|
||||
description: 'Learn how to integrate Slack with the Medusa backend. Learn how to create and configure a Slack app and install the Slack plugin on the Medusa backend.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Slack
|
||||
|
||||
In this documentation, you'll learn how to add the [Slack plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-slack-notification) to your Medusa backend to start receiving order notifications.
|
||||
|
||||
## Overview
|
||||
|
||||
When you add this plugin, the store owner can receive order notifications into their Slack workspace.
|
||||
|
||||
The notification contains details about the order including:
|
||||
|
||||
- Customer's details and address
|
||||
- Items ordered, their quantity, and the price
|
||||
- Order totals including Tax amount.
|
||||
- Promotion details if there are any (this is optional and can be turned off).
|
||||
|
||||
The plugin registers a subscriber to the `order.placed` event. When an order is placed, the subscriber handler method uses the ID of the order to retrieve order details mentioned above.
|
||||
|
||||
Then, the order notificaiton is sent to Slack using Webhooks. So, you'll need to create a Slack App, add it into your workspace, and activate Incoming Webhooks.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Slack Account
|
||||
|
||||
To follow along with this guide, you need to have a Slack account with a connected workspace. If you don’t have one, you can [create a free account on Slack](https://slack.com/).
|
||||
|
||||
### Medusa Backend
|
||||
|
||||
This tutorial assumes you already have a Medusa backend installed. If you don’t, please follow along with the [quickstart guide](../../development/backend/install.mdx).
|
||||
|
||||
### Redis
|
||||
|
||||
Medusa's event system works by pushing data into a queue that is based on [Redis](https://redis.io/). This queue then notifies handlers of different events of this data that is pushed into the queue. The handlers then use this data to perform a certain action.
|
||||
|
||||
As the Slack plugin will listen to the `order.placed` event to know when to send notifications, you'll need to have Redis installed and configured with your Medusa backend.
|
||||
|
||||
You can read the [Set up your development enviornment guideline](../../development/backend/prepare-environment.mdx#redis) to learn more about how you can install and setup Redis.
|
||||
|
||||
---
|
||||
|
||||
## Create Slack App
|
||||
|
||||
The first step is to create a Slack app. This app will be connected to your workspace and will have Incoming Webhooks activated to receive notifications from the Medusa backend using a Webhook URL.
|
||||
|
||||
Go to [Slack API](https://api.slack.com/) and click Create app. This will take you to a new page with a pop-up. In the pop-up, choose From scratch.
|
||||
|
||||

|
||||
|
||||
You’ll then need to enter some info like the App name and the workspace it will be connected to. Once you’re done, the app will be created.
|
||||
|
||||
### Activate Incoming Webhooks
|
||||
|
||||
To activate Incoming Webhooks, choose Features > Incoming Webhooks from the sidebar. At first, it will be disabled so make sure to enable it by switching the toggle.
|
||||
|
||||

|
||||
|
||||
### Add New Webhook
|
||||
|
||||
After activating Incoming Webhooks, on the same page scroll down and click on the Add New Webhook to Workspace button.
|
||||
|
||||

|
||||
|
||||
After that, choose the channel to send the notifications to. You can also choose a DM to send the notifications to. Once you’re done click Allow.
|
||||
|
||||

|
||||
|
||||
This will create a new Webhook with a URL which you can see in the table at the end of the Incoming Webhooks page. Copy the URL as you’ll use it in the next section.
|
||||
|
||||
---
|
||||
|
||||
## Install Slack Plugin
|
||||
|
||||
The next step is to install Medusa’s [Slack plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-slack-notification) into your Medusa backend.
|
||||
|
||||
Open the terminal in the Medusa backend’s directory and run the following command:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-slack-notification
|
||||
```
|
||||
|
||||
After that, open `medusa-config.js` and add the new plugin with its configurations in the `plugins` array:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...,
|
||||
{
|
||||
resolve: `medusa-plugin-slack-notification`,
|
||||
options: {
|
||||
show_discount_code: false,
|
||||
slack_url: `<WEBHOOK_URL>`,
|
||||
admin_orders_url: `http://localhost:7001/a/orders`,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
- Make sure to change `<WEBHOOK_URL>` with the Webhook URL you copied after creating the Slack app.
|
||||
- The `show_discount_code` option enables or disables showing the discount code in the notification sent to Slack.
|
||||
- The `admin_orders_url` is the prefix of the URL of the order detail pages on your admin panel. If you’re using Medusa’s Admin locally, it should be `http://localhost:7001/a/orders`. This will result in a URL like `http://localhost:7001/a/orders/order_01FYP7DM7PS43H9VQ1PK59ZR5G`.
|
||||
|
||||
That’s all you need to do to integrate Slack into Medusa!
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- Install [Medusa's Admin](../../admin/quickstart.mdx) for the full order-management experience.
|
||||
- Install the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) starter storefronts.
|
||||
147
docs/content/plugins/notifications/twilio-sms.md
Normal file
147
docs/content/plugins/notifications/twilio-sms.md
Normal file
@@ -0,0 +1,147 @@
|
||||
---
|
||||
description: 'Learn how to integrate Twilio SMS with the Medusa backend. Learn how to install the Twilio SMS plugin and test it out.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Twilio SMS
|
||||
|
||||
In this document, you’ll learn about the Twilio SMS Plugin, what it does, and how to use it in Medusa.
|
||||
|
||||
## Overview
|
||||
|
||||
[Twilio’s SMS API](https://www.twilio.com/sms) can be used to send users SMS messages instantly. It has a lot of additional features such as Whatsapp messaging and conversations.
|
||||
|
||||
By integrating Twilio SMS into Medusa, you’ll have easy access to Twilio’s SMS API to send SMS messages to your users and customers. You can use it to send Order confirmations, verification codes, reset password messages, and more.
|
||||
|
||||
:::note
|
||||
|
||||
This plugin only gives you access to the Twilio SMS API but does not implement sending messages at any given point. You’ll have to add this yourself where you need it. You can look at the [example later in this tutorial](#example-usage-of-the-plugin) to check how you can send an SMS for a new order.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before going further with this guide make sure you have a Medusa backend set up. You can follow the [Quickstart guide](../../development/backend/install.mdx) if you don’t.
|
||||
|
||||
You also must have a [Twilio account created](https://www.twilio.com/sms) so if you don’t already please go ahead and create one.
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Credentials
|
||||
|
||||
For the [Twilio SMS plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-twilio-sms), you need three credentials from your Twilio account: Account SID, Auth Token, and a Twilio phone number to send from. You can find these three from your [Twilio Console’s homepage](https://console.twilio.com).
|
||||
|
||||
---
|
||||
|
||||
## Install Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install [Twilio SMS plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-twilio-sms):
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-twilio-sms
|
||||
```
|
||||
|
||||
Then, you’ll need to add your credentials in `.env`:
|
||||
|
||||
```bash
|
||||
TWILIO_SMS_ACCOUNT_SID=<YOUR_ACCOUNT_SID>
|
||||
TWILIO_SMS_AUTH_TOKEN=<YOUR_AUTH_TOKEN>
|
||||
TWILIO_SMS_FROM_NUMBER=<YOUR_TWILIO_NUMBER>
|
||||
```
|
||||
|
||||
Make sure to replace `<YOUR_ACCOUNT_SID>`, `<YOUR_AUTH_TOKEN>`, and `<YOUR_TWILIO_NUMBER>` with the credentials you obtained from your Twilio Console.
|
||||
|
||||
Finally, add the plugin and its options in the `medusa-config.js` file to the `plugins` array:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-plugin-twilio-sms`,
|
||||
options: {
|
||||
account_sid: process.env.TWILIO_SMS_ACCOUNT_SID,
|
||||
auth_token: process.env.TWILIO_SMS_AUTH_TOKEN,
|
||||
from_number: process.env.TWILIO_SMS_FROM_NUMBER,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example Usage of the Plugin
|
||||
|
||||
This plugin adds the service `twilioSmsService` to your Medusa backend. To send SMS using it, all you have to do is resolve it in your file as explained in the [Services](../../development/services/create-service.md#using-your-custom-service) documentation.
|
||||
|
||||
In this example, you’ll create a subscriber that listens to the `order.placed` event and sends an SMS to the customer to confirm their order.
|
||||
|
||||
:::tip
|
||||
|
||||
For this example to work, you’ll need to install and configure Redis on your backend. You can refer to the [development guide](../../development/backend/prepare-environment.mdx#redis) to learn how to do that.
|
||||
|
||||
:::
|
||||
|
||||
Create the file `src/services/sms.js` in your Medusa backend with the following content:
|
||||
|
||||
```jsx title=src/services/sms.js
|
||||
class SmsSubscriber {
|
||||
constructor({
|
||||
twilioSmsService,
|
||||
orderService,
|
||||
eventBusService,
|
||||
}) {
|
||||
this.twilioSmsService_ = twilioSmsService
|
||||
this.orderService = orderService
|
||||
|
||||
eventBusService.subscribe("order.placed", this.sendSMS)
|
||||
}
|
||||
|
||||
sendSMS = async (data) => {
|
||||
const order = await this.orderService.retrieve(data.id, {
|
||||
relations: ["shipping_address"],
|
||||
})
|
||||
|
||||
if (order.shipping_address.phone) {
|
||||
this.twilioSmsService_.sendSms({
|
||||
to: order.shipping_address.phone,
|
||||
body: "We have received your order #" + data.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default SmsSubscriber
|
||||
```
|
||||
|
||||
In the `constructor`, you resolve the `twilioSmsService` and `orderService` using dependency injection to use it later in the `sendSMS` method.
|
||||
|
||||
You also subscribe to the event `order.placed` and sets the event handler to be `sendSMS`.
|
||||
|
||||
In `sendSMS`, you first retrieve the order with its relation to `shipping_address` which contains a `phone` field. If the phone is set, you send an SMS to the customer using the method `sendSms` in the `twilioSmsService`.
|
||||
|
||||
This method accepts an object of parameters. These parameters are based on Twilio’s SMS APIs. You can check their [API documentation](https://www.twilio.com/docs/sms/api/message-resource#create-a-message-resource) for more fields that you can add.
|
||||
|
||||
If you create an order now on your storefront, you should receive a message from Twilio on the phone number you entered in the shipping address.
|
||||
|
||||
:::tip
|
||||
|
||||
If you don’t have a storefront set up yet, you can install one of the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts.
|
||||
|
||||
:::
|
||||
|
||||
:::caution
|
||||
|
||||
If you’re on a Twilio trial make sure that the phone number you entered on checkout is a [verified Twilio number on your console](https://console.twilio.com/us1/develop/phone-numbers/manage/verified).
|
||||
|
||||
:::
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Notifications Overview](../../development/notification/overview.mdx).
|
||||
- Install the [Medusa admin](../../admin/quickstart.mdx) for functionalities like Gift Cards creation, swaps, claims, order return requests, and more.
|
||||
79
docs/content/plugins/overview.mdx
Normal file
79
docs/content/plugins/overview.mdx
Normal file
@@ -0,0 +1,79 @@
|
||||
---
|
||||
description: 'Check out available official plugins in Medusa.'
|
||||
---
|
||||
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
import Icons from '@theme/Icon';
|
||||
|
||||
# Plugins
|
||||
|
||||
This section includes documentation for official Medusa plugins.
|
||||
|
||||
You can learn more about plugins and how they work in the [Plugins Overview documentation](../development/plugins/overview.mdx).
|
||||
|
||||
:::tip
|
||||
|
||||
Interested in creating a plugin? Learn more in the [Create Plugin documentation](../development/plugins/create).
|
||||
|
||||
:::
|
||||
|
||||
<!-- vale docs.Acronyms = NO -->
|
||||
|
||||
<DocCardList colSize={6} items={[
|
||||
{
|
||||
type: 'link',
|
||||
href: '/plugins/analytics',
|
||||
label: 'Analytics',
|
||||
customProps: {
|
||||
icon: Icons['squares-plus-solid'],
|
||||
description: 'Check out available official Analytics plugins.'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/plugins/cms',
|
||||
label: 'CMS',
|
||||
customProps: {
|
||||
icon: Icons['squares-plus-solid'],
|
||||
description: 'Check out available official CMS plugins.'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/plugins/notifications',
|
||||
label: 'Notifications',
|
||||
customProps: {
|
||||
icon: Icons['squares-plus-solid'],
|
||||
description: 'Check out available official Notifications plugins.'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/plugins/payment',
|
||||
label: 'Payment',
|
||||
customProps: {
|
||||
icon: Icons['squares-plus-solid'],
|
||||
description: 'Check out available official Payment plugins.'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/plugins/search',
|
||||
label: 'Search',
|
||||
customProps: {
|
||||
icon: Icons['squares-plus-solid'],
|
||||
description: 'Check out available official Search plugins.'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/plugins/file-service',
|
||||
label: 'File Service',
|
||||
customProps: {
|
||||
icon: Icons['squares-plus-solid'],
|
||||
description: 'Check out available official File Service plugins.'
|
||||
}
|
||||
},
|
||||
]} />
|
||||
|
||||
<!-- vale docs.Acronyms = YES -->
|
||||
5
docs/content/plugins/payment/index.mdx
Normal file
5
docs/content/plugins/payment/index.mdx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Payment Plugins
|
||||
|
||||
<DocCardList />
|
||||
93
docs/content/plugins/payment/klarna.md
Normal file
93
docs/content/plugins/payment/klarna.md
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
description: 'Learn how to integrate Klarna as a payment provider with the Medusa backend. Learn how to install Klarna and enable the payment provider in a region.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Klarna
|
||||
|
||||
In this document, you’ll learn how to integrate Klarna as a payment provider in Medusa.
|
||||
|
||||
## Introduction
|
||||
|
||||
[Klarna](https://www.klarna.com/) is a payment provider that allows customers to pay in different ways including direct payment, installment payments, payment after delivery, and more.
|
||||
|
||||
You can integrate Klarna into Medusa using the [official plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-payment-klarna).
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Components
|
||||
|
||||
It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../development/backend/install.mdx).
|
||||
|
||||
In addition, you’ll need to use the [Medusa Admin](../../admin/quickstart.mdx) to enable the payment provider in later steps. You can alternatively use the [REST APIs](/api/admin/#tag/Region/operation/PostRegionsRegionPaymentProviders).
|
||||
|
||||
### Needed Accounts
|
||||
|
||||
- A [Klarna business account](https://portal.klarna.com/)
|
||||
|
||||
---
|
||||
|
||||
## Install Plugin
|
||||
|
||||
On your Medusa backend, run the following command to install the plugin:
|
||||
|
||||
```bash
|
||||
npm install medusa-payment-klarna
|
||||
```
|
||||
|
||||
Then, add the following environment variables:
|
||||
|
||||
```bash
|
||||
KLARNA_BACKEND_URL=<YOUR_KLARNA_BACKEND_URL>
|
||||
KLARNA_URL=<YOUR_KLARNA_URL>
|
||||
KLARNA_USER=<YOUR_KLARNA_USER>
|
||||
KLARNA_PASSWORD=<YOUR_KLARNA_PASSWORD>
|
||||
KLARNA_TERMS_URL=<YOUR_KLARNA_TERMS_URL>
|
||||
KLARNA_CHECKOUT_URL=<YOUR_KLARNA_CHECKOUT_URL>
|
||||
KLARNA_CONFIRMATION_URL=<YOUR_KLARNA_CONFIRMATION_URL>
|
||||
```
|
||||
|
||||
Where:
|
||||
|
||||
- `<YOUR_KLARNA_BACKEND_URL>` is your Klarna URL.
|
||||
- `<YOUR_KLARNA_URL>` is the [base Klarna URL based on your environment](https://docs.klarna.com/api/api-urls/).
|
||||
- `<YOUR_KLARNA_USER>` and `<YOUR_KLARNA_PASSWORD>` are your [API credentials](https://docs.klarna.com/api/authentication/).
|
||||
- `<YOUR_KLARNA_TERMS_URL>`, `<YOUR_KLARNA_CHECKOUT_URL>`, and `<YOUR_KLARNA_CONFIRMATION_URL>` are the terms, checkout, and confirmation URL of your Klarna account.
|
||||
|
||||
Finally, in `medusa-config.js`, add the Klarna plugin to the `plugins` array with the necessary configurations:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// other plugins...
|
||||
{
|
||||
resolve: `medusa-payment-klarnal`,
|
||||
options: {
|
||||
backend_url: process.env.KLARNA_BACKEND_URL,
|
||||
url: process.env.KLARNA_URL,
|
||||
user: process.env.KLARNA_USER,
|
||||
password: process.env.KLARNA_PASSWORD,
|
||||
merchant_urls: {
|
||||
terms: process.env.KLARNA_TERMS_URL,
|
||||
checkout: process.env.KLARNA_CHECKOUT_URL,
|
||||
confirmation: process.env.KLARNA_CONFIRMATION_URL,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Enable Klarna in Regions
|
||||
|
||||
To use Klarna in your store, you must enable it in at least one region.
|
||||
|
||||
You can follow [this user guide to learn how to enable a payment provider in a region](../../user-guide/regions/providers#manage-payment-providers). You can alternatively use the [REST APIs](/api/admin/#tag/Region/operation/PostRegionsRegionPaymentProviders).
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- Check out [more plugins](../overview.mdx) you can add to your store.
|
||||
438
docs/content/plugins/payment/paypal.md
Normal file
438
docs/content/plugins/payment/paypal.md
Normal file
@@ -0,0 +1,438 @@
|
||||
---
|
||||
description: 'Learn how to integrate PayPal with the Medusa backend. Learn how to install the PayPal plugin on the Medusa backend and integrate into a storefront.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# PayPal
|
||||
|
||||
This document guides you through setting up PayPal as a payment provider in your Medusa backend, admin, and storefront using the [PayPal plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-payment-paypal).
|
||||
|
||||
## Overview
|
||||
|
||||
[PayPal](https://www.paypal.com) is a payment provider used by millions around the world. It allows customers to purchase orders from your website using their PayPal account rather than the need to enter their card details.
|
||||
|
||||
As a developer, you can use PayPal’s SDKs and APIs to integrate PayPal as a payment method into your ecommerce store. You can test out the payment method in sandbox mode before going live with it as a payment method.
|
||||
|
||||
Using the `medusa-payment-paypal` plugin, this guide shows you how to set up your Medusa backend with PayPal as a payment provider.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you proceed with this guide, make sure you create a [PayPal account](https://www.paypal.com). You also need a PayPal Developer account and retrieve the Client ID and Client Secret. You can learn more about how to do that in [PayPal’s documentation](https://developer.paypal.com/api/rest/).
|
||||
|
||||
In addition, you need to configure a webhook listener on your PayPal Developer Dashboard and obtain the webhook ID. This is necessary for Webhooks to work.
|
||||
|
||||
Webhooks are used in scenarios where the customer might leave the page during the authorization and before the checkout flow is fully complete. It will then create the order or swap after the payment is authorized if they weren’t created
|
||||
|
||||
Additionally, you need a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../development/backend/install.mdx) to get started.
|
||||
|
||||
You also need [Medusa Admin](../../admin/quickstart.mdx) installed to enable PayPal as a payment provider. You can alternatively use the [REST APIs](/api/admin).
|
||||
|
||||
---
|
||||
|
||||
## Medusa Backend
|
||||
|
||||
### Install the PayPal Plugin
|
||||
|
||||
In the root of your Medusa backend, run the following command to install the PayPal plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-payment-paypal
|
||||
```
|
||||
|
||||
### Configure the PayPal Plugin
|
||||
|
||||
Next, you need to add configurations for your PayPal plugin.
|
||||
|
||||
In the `.env` file add the following new environment variables:
|
||||
|
||||
```bash
|
||||
PAYPAL_SANDBOX=true
|
||||
PAYPAL_CLIENT_ID=<CLIENT_ID>
|
||||
PAYPAL_CLIENT_SECRET=<CLIENT_SECRET>
|
||||
PAYPAL_AUTH_WEBHOOK_ID=<WEBHOOK_ID>
|
||||
```
|
||||
|
||||
Where `<CLIENT_ID>`, `<CLIENT_SECRET>`, and `<WEBHOOK_ID>` are the keys you retrieved from the PayPal Developer dashboard as explained in the [Prerequisites](#prerequisites) section.
|
||||
|
||||
Notice that during development it’s highly recommended to set `PAYPAL_SANDBOX` to `true` and ensure you have [sandbox accounts set up in PayPal](https://developer.paypal.com/api/rest/sandbox/).
|
||||
|
||||
Then, in `medusa-config.js`, add the PayPal plugin to the `plugins` array with the configurations necessary:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// other plugins...
|
||||
{
|
||||
resolve: `medusa-payment-paypal`,
|
||||
options: {
|
||||
sandbox: process.env.PAYPAL_SANDBOX,
|
||||
client_id: process.env.PAYPAL_CLIENT_ID,
|
||||
client_secret: process.env.PAYPAL_CLIENT_SECRET,
|
||||
auth_webhook_id: process.env.PAYPAL_AUTH_WEBHOOK_ID,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
That’s all you need to install PayPal on your Medusa backend!
|
||||
|
||||
---
|
||||
|
||||
## Admin Setup
|
||||
|
||||
This section will guide you through adding PayPal as a payment provider in a region using your Medusa admin dashboard.
|
||||
|
||||
This step is required for you to be able to use PayPal as a payment provider in your storefront.
|
||||
|
||||
### Admin Prerequisites
|
||||
|
||||
If you don’t have a Medusa admin installed, make sure to follow along with [the guide on how to install it](../../admin/quickstart.mdx) before continuing with this section.
|
||||
|
||||
### Add PayPal to Regions
|
||||
|
||||
You can refer to [this documentation in the user guide](../../user-guide/regions/providers.mdx#manage-payment-providers) to learn how to add a payment provider like PayPal to a region.
|
||||
|
||||
---
|
||||
|
||||
## Storefront Setup
|
||||
|
||||
This section will take you through the steps to add PayPal as a payment method on the storefront. It includes the steps necessary when using one of Medusa’s official storefronts as well as your own custom React-based storefront.
|
||||
|
||||
### Storefront Prerequisites
|
||||
|
||||
All storefronts require that you obtain your PayPal Client ID. You can retrieve it from your PayPal developer dashboard.
|
||||
|
||||
### Process Overview
|
||||
|
||||
Aside from the Next.js Storefront, you need to add the implementation with PayPal manually.
|
||||
|
||||
:::note
|
||||
|
||||
It is recommended to read through the [Frontend Checkout Flow](../../modules/carts-and-checkout/storefront/implement-checkout-flow.mdx) first to fully understand how payment is implemented on the storefront.
|
||||
|
||||
:::
|
||||
|
||||
Although the next sections have different implementations to add PayPal into your storefront, they essentially follow the same process:
|
||||
|
||||
1. Show PayPal’s button if the PayPal provider is available for the current cart.
|
||||
2. When the button is clicked, open PayPal’s payment portal and wait for the customer to authorize the payment.
|
||||
3. If the payment is authorized successfully, set PayPal’s [Payment Session](../../modules/carts-and-checkout/payment.md#payment-session) as the session used to perform the payment for the current cart, then update the Payment Session on the backend with the data received from PayPal’s payment portal. This data is essential to the backend to verify the authorization and perform additional payment processing later such as capturing payment.
|
||||
4. Complete the cart to create the order.
|
||||
|
||||
:::info
|
||||
|
||||
In Medusa, by default, payments are authorized during checkout, but the payment is not captured right away. The payment should be manually [captured from the Medusa Admin](#capture-payment).
|
||||
|
||||
:::
|
||||
|
||||
### Add to Next.js Storefront
|
||||
|
||||
Medusa has a Next.js storefront that you can easily use with your Medusa backend. If you don’t have the storefront installed, you can follow [this quickstart guide](../../starters/nextjs-medusa-starter.mdx).
|
||||
|
||||
In your `.env.local` file (or the file you’re using for your environment variables), add the following variable:
|
||||
|
||||
```bash title=.env.local
|
||||
NEXT_PUBLIC_PAYPAL_CLIENT_ID=<YOUR_CLIENT_ID>
|
||||
```
|
||||
|
||||
Make sure to replace `<YOUR_CLIENT_ID>` with your PayPal Client ID.
|
||||
|
||||
Now, if you run your Medusa backend and your storefront, on checkout you’ll be able to use PayPal].
|
||||
|
||||

|
||||
|
||||
You can test out the payment with PayPal using your sandbox account.
|
||||
|
||||
### Add to Gatsby Storefront
|
||||
|
||||
Medusa also has a Gatsby storefront that you can use as your ecommerce storefront. If you don’t have the storefront installed, you can follow [this quickstart guide](../../starters/gatsby-medusa-starter.mdx).
|
||||
|
||||
In your `.env.development` file (or the file you’re using for your environment variables) add the following variable with its value set to the Client ID:
|
||||
|
||||
```bash title=.env.development
|
||||
GATSBY_PAYPAL_CLIENT_ID=<CLIENT_ID>
|
||||
```
|
||||
|
||||
Then, install [PayPal’s React components](https://www.npmjs.com/package/@paypal/react-paypal-js) library:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install @paypal/react-paypal-js
|
||||
```
|
||||
|
||||
Next, create a new file `src/components/payment/paypal-payment/index.jsx` with the following content:
|
||||
|
||||
```jsx title=src/components/payment/paypal-payment/index.jsx
|
||||
import {
|
||||
PayPalButtons,
|
||||
PayPalScriptProvider,
|
||||
} from "@paypal/react-paypal-js"
|
||||
import React, { useMemo, useState } from "react"
|
||||
|
||||
import { navigate } from "gatsby"
|
||||
import { useCart } from "../../../hooks/use-cart"
|
||||
import { useMedusa } from "../../../hooks/use-medusa"
|
||||
|
||||
const paypalClientId = process.env.GATSBY_PAYPAL_CLIENT_ID || ""
|
||||
|
||||
const PaypalPayment = () => {
|
||||
const {
|
||||
cart,
|
||||
actions: { completeCart, setPaymentSession },
|
||||
} = useCart()
|
||||
const [errorMessage, setErrorMessage] = useState(undefined)
|
||||
const [processing, setProcessing] = useState(false)
|
||||
|
||||
const client = useMedusa()
|
||||
|
||||
const paypalSession = useMemo(() => {
|
||||
if (cart.payment_sessions) {
|
||||
return cart.payment_sessions.find(
|
||||
(s) => s.provider_id === "paypal"
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}, [cart.payment_sessions])
|
||||
|
||||
if (!paypalSession) {
|
||||
return null
|
||||
}
|
||||
|
||||
const completeOrder = async (authorizationOrder) => {
|
||||
const cart = await setPaymentSession("paypal")
|
||||
|
||||
if (!cart) {
|
||||
setProcessing(false)
|
||||
return
|
||||
}
|
||||
|
||||
await client.carts.updatePaymentSession(cart.id, "paypal", {
|
||||
data: {
|
||||
data: {
|
||||
...authorizationOrder,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const order = await completeCart(cart.id)
|
||||
|
||||
if (!order || order.object !== "order") {
|
||||
setProcessing(false)
|
||||
return
|
||||
}
|
||||
|
||||
setProcessing(false)
|
||||
navigate("/order-confirmed", { state: { order } })
|
||||
}
|
||||
|
||||
const handlePayment = (data, actions) => {
|
||||
actions.order.authorize().then((authorization) => {
|
||||
if (authorization.status !== "COMPLETED") {
|
||||
setErrorMessage(
|
||||
`An error occurred, status: ${authorization.status}`
|
||||
)
|
||||
setProcessing(false)
|
||||
return
|
||||
}
|
||||
|
||||
completeOrder(authorization)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<PayPalScriptProvider options={{
|
||||
"client-id": paypalClientId,
|
||||
"currency": cart.region.currency_code.toUpperCase(),
|
||||
"intent": "authorize",
|
||||
}}>
|
||||
{errorMessage && (
|
||||
<span className="text-rose-500 mt-4">
|
||||
{errorMessage}
|
||||
</span>
|
||||
)}
|
||||
<PayPalButtons
|
||||
style={{ layout: "horizontal" }}
|
||||
onApprove={handlePayment}
|
||||
disabled={processing}
|
||||
/>
|
||||
</PayPalScriptProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default PaypalPayment
|
||||
```
|
||||
|
||||
Here’s briefly what this code snippet does:
|
||||
|
||||
1. This component renders a PayPal button to initialize the payment using PayPal. You use the components from the PayPal React components library to render the button and you pass the `PayPalScriptProvider` component the Client ID.
|
||||
2. When the button is clicked, the `handlePayment` function is executed. In this method, you initialize the payment authorization using `actions.order.authorize()`. It takes the customer to another page to log in with PayPal and authorize the payment.
|
||||
3. After the payment is authorized successfully on PayPal’s portal, the fulfillment function passed to `actions.order.authorize().then` will be executed which calls the `completeOrder` function.
|
||||
4. In `completeOrder`, you first ensure that the payment session for the PayPal payment provider is set as the [selected Payment Session in the cart](/api/store/#tag/Cart/operation/PostCartsCartPaymentSession). Then, you send a request to the backend to [update the payment session](/api/store#tag/Cart/operation/PostCartsCartPaymentSessionUpdate) data with the authorization data received from PayPal.
|
||||
5. You then [complete the cart and place the order](/api/store/#tag/Cart/operation/PostCartsCartComplete). If that is done successfully, you navigate to the `/order-confirmed` page.
|
||||
|
||||
The last step is to add this component as the component to render when PayPal is available as a payment provider.
|
||||
|
||||
In `src/components/payment/index.js` you’ll find in the return statement a switch statement that checks the payment provider for each payment session and renders the component based on the ID. Add before the `default` case a case for `paypal`:
|
||||
|
||||
```jsx title=src/components/payment/index.js
|
||||
switch (ps.provider_id) {
|
||||
case "stripe":
|
||||
// ...
|
||||
break
|
||||
case "manual":
|
||||
// ...
|
||||
break
|
||||
case "paypal":
|
||||
return <PaypalPayment />
|
||||
default:
|
||||
return null
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to also import the `PayPalPayment` component at the top of the file:
|
||||
|
||||
```jsx
|
||||
import PaypalPayment from "./paypal-payment"
|
||||
```
|
||||
|
||||
That’s all you need to integrate PayPal into the Gatsby storefront.
|
||||
|
||||
Now, start the Medusa backend and the Gatsby storefront backend. Try adding an item into the cart and proceeding to checkout. When you reach the payment step, you should see the PayPal button.
|
||||
|
||||

|
||||
|
||||
You can test out the payment with PayPal using your sandbox account.
|
||||
|
||||
### Add to Custom Storefront
|
||||
|
||||
This section guides you to add PayPal into a React-based framework. The instructions are general instructions that you can use in your storefront.
|
||||
|
||||
In your storefront, you need to install the [PayPal React components library](https://www.npmjs.com/package/@paypal/react-paypal-js) and the [Medusa JS Client library](https://www.npmjs.com/package/@medusajs/medusa-js):
|
||||
|
||||
```bash npm2yarn
|
||||
npm install @paypal/react-paypal-js @medusajs/medusa-js
|
||||
```
|
||||
|
||||
Then, add the Client ID as an environment variable based on the framework you’re using.
|
||||
|
||||
Next, create the file that will hold the PayPal component with the following content:
|
||||
|
||||
```jsx
|
||||
import {
|
||||
PayPalButtons,
|
||||
PayPalScriptProvider,
|
||||
} from "@paypal/react-paypal-js"
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
import Medusa from "@medusajs/medusa-js"
|
||||
|
||||
function Paypal() {
|
||||
const client = new Medusa()
|
||||
const [errorMessage, setErrorMessage] = useState(undefined)
|
||||
const [processing, setProcessing] = useState(false)
|
||||
const cart = "..." // TODO retrieve the cart here
|
||||
|
||||
const handlePayment = (data, actions) => {
|
||||
actions.order.authorize().then(async (authorization) => {
|
||||
if (authorization.status !== "COMPLETED") {
|
||||
setErrorMessage(
|
||||
`An error occurred, status: ${authorization.status}`
|
||||
)
|
||||
setProcessing(false)
|
||||
return
|
||||
}
|
||||
|
||||
const response = await client
|
||||
.carts
|
||||
.setPaymentSession(cart.id, {
|
||||
"provider_id": "paypal",
|
||||
})
|
||||
|
||||
if (!response.cart) {
|
||||
setProcessing(false)
|
||||
return
|
||||
}
|
||||
|
||||
await client
|
||||
.carts
|
||||
.updatePaymentSession(cart.id, "paypal", {
|
||||
data: {
|
||||
data: {
|
||||
...authorization,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { data } = await client.carts.complete(cart.id)
|
||||
|
||||
if (!data || data.object !== "order") {
|
||||
setProcessing(false)
|
||||
return
|
||||
}
|
||||
|
||||
// order successful
|
||||
alert("success")
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ marginTop: "10px", marginLeft: "10px" }}>
|
||||
{cart !== undefined && (
|
||||
<PayPalScriptProvider options={{
|
||||
"client-id": "<CLIENT_ID>",
|
||||
"currency": "EUR",
|
||||
"intent": "authorize",
|
||||
}}>
|
||||
{errorMessage && (
|
||||
<span className="text-rose-500 mt-4">
|
||||
{errorMessage}
|
||||
</span>
|
||||
)}
|
||||
<PayPalButtons
|
||||
style={{ layout: "horizontal" }}
|
||||
onApprove={handlePayment}
|
||||
disabled={processing}
|
||||
/>
|
||||
</PayPalScriptProvider>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Paypal
|
||||
```
|
||||
|
||||
Here’s briefly what this code snippet does:
|
||||
|
||||
1. At the beginning of the component, the Medusa client is initialized using the JS Client you installed.
|
||||
2. You also need to retrieve the cart. Ideally, the cart should be managed through a context. So, every time the cart has been updated the cart should be updated in the context to be accessed from all components.
|
||||
3. This component renders a PayPal button to initialize the payment using PayPal. You use the components from the PayPal React components library to render the button and you pass the `PayPalScriptProvider` component the Client ID. Make sure to replace `<CLIENT_ID>` with the environment variable you added.
|
||||
4. When the button is clicked, the `handlePayment` function is executed. In this method, you initialize the payment authorization using `actions.order.authorize()`. It takes the customer to another page to log in with PayPal and authorize the payment.
|
||||
5. After the payment is authorized successfully on PayPal’s portal, the fulfillment function passed to `actions.order.authorize().then` will be executed.
|
||||
6. In the fulfillment function, you first ensure that the payment session for the PayPal payment provider is set as the [selected Payment Session in the cart](/api/store/#tag/Cart/operation/PostCartsCartPaymentSession). Then, you send a request to the backend to [update the payment session](/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionUpdate) data with the authorization data received from PayPal.
|
||||
7. You then [complete the cart and place the order](/api/store/#tag/Cart/operation/PostCartsCartComplete). If that is done successfully, you just show a success alert. You can change this based on the behavior you want in your storefront.
|
||||
|
||||
You can then import this component where you want to show it in your storefront.
|
||||
|
||||
If you run the Medusa backend and the storefront backend, you should see the PayPal button on checkout.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Capture Payments
|
||||
|
||||
After the customer places an order, you can see the order on the admin panel. In the payment information under the “Payment” section, you should see a “Capture” button.
|
||||
|
||||

|
||||
|
||||
Clicking this button lets you capture the payment for an order. You can also refund payments if an order has captured payments.
|
||||
|
||||
Refunding or Capturing payments is reflected in your PayPal dashboard as well.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- Check out [more plugins](../overview.mdx) you can add to your store.
|
||||
388
docs/content/plugins/payment/stripe.md
Normal file
388
docs/content/plugins/payment/stripe.md
Normal file
@@ -0,0 +1,388 @@
|
||||
---
|
||||
description: 'Learn how to integrate Stripe with the Medusa backend. Learn how to install the Stripe plugin on the Medusa backend and integrate it into a storefront.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Stripe
|
||||
|
||||
This document guides you through setting up Stripe payments in your Medusa backend, admin, and storefront using the [Stripe Plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-payment-stripe).
|
||||
|
||||
## Video Guide
|
||||
|
||||
You can also follow this video guide to learn how the setup works:
|
||||
|
||||
<div>
|
||||
<video width="100%" height="100%" playsinline autoplay muted controls>
|
||||
<source src="https://user-images.githubusercontent.com/59018053/154807206-6fbda0a6-bf3e-4e39-9fc2-f11710afe0b9.mp4" type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
[Stripe](https://stripe.com/) is a battle-tested and unified platform for transaction handling. Stripe supplies you with the technical components needed to handle transactions safely and all the analytical features necessary to gain insight into your sales. These features are also available in a safe test environment which allows for a concern-free development process.
|
||||
|
||||
Using the `medusa-payment-stripe` plugin, this guide shows you how to set up your Medusa project with Stripe as a payment provider.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you proceed with this guide, make sure you create a [Stripe account](https://stripe.com). You’ll later retrieve the API Keys and secrets from your account to connect Medusa to your Stripe account.
|
||||
|
||||
---
|
||||
|
||||
## Medusa Backend
|
||||
|
||||
This section guides you over the steps necessary to add Stripe as a payment provider to your Medusa backend.
|
||||
|
||||
If you don’t have a Medusa backend installed yet, you must follow the [quickstart guide](../../development/backend/install.mdx) first.
|
||||
|
||||
### Install the Stripe Plugin
|
||||
|
||||
In the root of your Medusa backend, run the following command to install the stripe plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-payment-stripe
|
||||
```
|
||||
|
||||
### Configure the Stripe Plugin
|
||||
|
||||
Next, you need to add configurations for your stripe plugin.
|
||||
|
||||
In `medusa-config.js` add the following at the end of the `plugins` array:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-payment-stripe`,
|
||||
options: {
|
||||
api_key: process.env.STRIPE_API_KEY,
|
||||
webhook_secret: process.env.STRIPE_WEBHOOK_SECRET,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
You might find that this code is already available but commented out. You can proceed with removing the comments instead of adding the code again, but make sure to replace `STRIPE_API_KEY` and `STRIPE_WEBHOOK_SECRET` with `process.env.STRIPE_API_KEY` and `process.env.STRIPE_WEBHOOK_SECRET` respectively.
|
||||
|
||||
:::
|
||||
|
||||
The Stripe plugin uses two configuration options. The `api_key` is essential to both your development and production environments. As for the `webhook_secret`, it’s essential for your production environment. So, if you’re only using Stripe for development you can skip adding the value for this option at the moment.
|
||||
|
||||
### Retrieve Stripe's Keys
|
||||
|
||||
On the [dashboard](https://dashboard.stripe.com) of your Stripe account click on the Developers link at the top right. This will take you to the developer dashboard.
|
||||
|
||||
You’ll first retrieve the API key. You can find it by choosing API Keys from the sidebar and copying the Secret key.
|
||||
|
||||
Next, you need to add the key to your environment variables. In your Medusa backend, create `.env` if it doesn’t already exist and add the Stripe key:
|
||||
|
||||
```bash
|
||||
STRIPE_API_KEY=sk_...
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
If you store environment variables differently on your backend, for example, using the hosting provider’s UI, then you don’t need to add it in `.env`. Add the environment variables in a way relevant to your backend.
|
||||
|
||||
:::
|
||||
|
||||
Next, if you’re installing this plugin for production use, you need to retrieve the Webhook secret. Webhooks allows you to track different events on your Medusa backend, such as failed payments.
|
||||
|
||||
Go to Webhooks on Stripe’s developer dashboard. Then, choose the Add an Endpoint button.
|
||||
|
||||
The endpoint for Stripe’s webhook on your Medusa backend is `{BACKEND_URL}/stripe/hooks`. So, add that endpoint in its field. Make sure to replace `{BACKEND_URL}` with the URL to your backend.
|
||||
|
||||
Then, you can add a description. You must select at least one event to listen to. Once you’re done, click “Add endpoint”.
|
||||
|
||||
After the Webhook is created, you’ll see "Signing secret" in the Webhook details. Click on "Reveal" to reveal the secret key. Copy that key and in your Medusa backend add the Webhook secret environment variable:
|
||||
|
||||
```bash
|
||||
STRIPE_WEBHOOK_SECRET=whsec_...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Admin Setup
|
||||
|
||||
This section will guide you through adding Stripe as a payment provider in a region using your Medusa admin dashboard.
|
||||
|
||||
This step is required for you to be able to use Stripe as a payment provider in your storefront.
|
||||
|
||||
### Admin Prerequisites
|
||||
|
||||
If you don’t have a Medusa admin installed, make sure to follow along with [the guide on how to install it](https://github.com/medusajs/admin#-quickstart) before continuing with this section.
|
||||
|
||||
### Add Stripe to Regions
|
||||
|
||||
You can refer to [this documentation in the user guide](../../user-guide/regions/providers.mdx#manage-payment-providers) to learn how to add a payment provider like Stripe to a region.
|
||||
|
||||
---
|
||||
|
||||
## Storefront Setup
|
||||
|
||||
This guide will take you through how to set up Stripe payments in your Medusa storefront. It includes the steps necessary when using one of Medusa’s official storefronts as well as your own custom React-based storefront.
|
||||
|
||||
### Storefront Prerequisites
|
||||
|
||||
All storefronts require that you obtain your Stripe’s Publishable Key. You can retrieve it from your Stripe’s developer dashboard by choosing API Keys and then copying the Publishable Key.
|
||||
|
||||
### Add to Next.js Storefront
|
||||
|
||||
Medusa has a Next.js storefront that you can easily use with your Medusa backend. If you don’t have the storefront installed, you can follow [this quickstart guide](../../starters/nextjs-medusa-starter).
|
||||
|
||||
In your `.env.local` file (or the file you’re using for your environment variables), add the following variable:
|
||||
|
||||
```bash title=.env.local
|
||||
NEXT_PUBLIC_STRIPE_KEY=<YOUR_PUBLISHABLE_KEY>
|
||||
```
|
||||
|
||||
Make sure to replace `<YOUR_PUBLISHABLE_KEY>` with your Stripe Publishable Key.
|
||||
|
||||
Now, if you run your Medusa backend and your storefront, on checkout you’ll be able to use Stripe.
|
||||
|
||||

|
||||
|
||||
### Add to Gatsby Storefront
|
||||
|
||||
Medusa also has a Gatsby storefront that you can use as your ecommerce store. If you don’t have the storefront installed, you can follow [this quickstart guide](../../starters/gatsby-medusa-starter).
|
||||
|
||||
In your `.env.development` file (or the file you’re using for your environment variables) add the following variable with the value set to the Publishable Key:
|
||||
|
||||
```jsx title=.env.development
|
||||
GATSBY_STRIPE_KEY=pk_
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
You might find this environment variable already available so you can just replace its value with your Publishable Key.
|
||||
|
||||
:::
|
||||
|
||||
Now, if you run your Medusa backend and your storefront, on checkout you’ll be able to use Stripe.
|
||||
|
||||

|
||||
|
||||
### Add to Custom Storefront
|
||||
|
||||
This section will go over how to add Stripe into a React-based framework. The instructions are general instructions that you can use in your storefront.
|
||||
|
||||
#### Workflow Overview
|
||||
|
||||
The integration with stripe must have the following workflow:
|
||||
|
||||
1. During checkout when the user reaches the payment section, you should [create payment sessions](/api/store/#tag/Cart/operation/PostCartsCartPaymentSessions). This will initialize the `payment_sessions` array in the `cart` object received. The `payment_sessions` is an array of available payment providers.
|
||||
2. If Stripe is available as a payment provider, you should select Stripe as [the payment session](/api/store/#tag/Cart/operation/PostCartsCartPaymentSession) for the current cart. This will initialize the `payment_session` object in the `cart` object to include data related to Stripe and the current payment session. This includes the payment intent and client secret.
|
||||
3. After the user enters their card details and submits the form, confirm the payment with Stripe.
|
||||
4. If the payment is confirmed successfully, [complete the order](/api/store/#tag/Cart/operation/PostCartsCartComplete) in Medusa. Otherwise show an error.
|
||||
|
||||
#### Install Dependencies
|
||||
|
||||
Before you start the implementations you need to install the necessary dependencies. You’ll be using Stripe’s React libraries to show the UI and handle the payment confirmation:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install --save @stripe/react-stripe-js @stripe/stripe-js
|
||||
```
|
||||
|
||||
You’ll also use Medusa’s JS Client to easily call Medusa’s REST APIs:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install @medusajs/medusa-js
|
||||
```
|
||||
|
||||
#### Initialize Stripe
|
||||
|
||||
In this section, you’ll initialize Stripe without Medusa’s checkout workflow. Please note that this is one approach to add Stripe into your React project. You can check out [Stripe’s React documentation](https://stripe.com/docs/stripe-js/react) for other methods or components.
|
||||
|
||||
Create a container component that will hold the payment card component:
|
||||
|
||||
```jsx
|
||||
import { useState } from "react"
|
||||
|
||||
import { Elements } from "@stripe/react-stripe-js"
|
||||
import Form from "./Form"
|
||||
import { loadStripe } from "@stripe/stripe-js"
|
||||
|
||||
const stripePromise = loadStripe("pk_...")
|
||||
|
||||
export default function Container() {
|
||||
const [clientSecret, setClientSecret] = useState()
|
||||
|
||||
// TODO set clientSecret
|
||||
|
||||
return (
|
||||
<div>
|
||||
{clientSecret && (
|
||||
<Elements stripe={stripePromise} options={{
|
||||
clientSecret,
|
||||
}}>
|
||||
<Form clientSecret={clientSecret} cartId={cartId} />
|
||||
</Elements>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
```
|
||||
|
||||
In this component, you need to use Stripe’s `loadStripe` function outside of the component’s implementation to ensure that Stripe doesn’t re-load with every change. The function accepts the Publishable Key.
|
||||
|
||||
:::note
|
||||
|
||||
You’ll probably store this Publishable Key in an environment variable depending on your framework. It’s hard-coded here for simplicity.
|
||||
|
||||
:::
|
||||
|
||||
Then, inside the component’s implementation, you add a state variable `clientSecret` which you’ll retrieve in the next section.
|
||||
|
||||
Once the clientSecret is set, the `Elements` Stripe component will wrap a `Form` component you’ll create next. This is necessary because the `Elements` component allows child elements to get access to the card’s inputs and their data using Stripe’s `useElements` hook.
|
||||
|
||||
Create a new file for the `Form` component with the following content:
|
||||
|
||||
```jsx
|
||||
import {
|
||||
CardElement,
|
||||
useElements,
|
||||
useStripe,
|
||||
} from "@stripe/react-stripe-js"
|
||||
|
||||
export default function Form({ clientSecret, cartId }) {
|
||||
const stripe = useStripe()
|
||||
const elements = useElements()
|
||||
|
||||
async function handlePayment(e) {
|
||||
e.preventDefault()
|
||||
// TODO handle payment
|
||||
}
|
||||
|
||||
return (
|
||||
<form>
|
||||
<CardElement />
|
||||
<button onClick={handlePayment}>Submit</button>
|
||||
</form>
|
||||
)
|
||||
};
|
||||
```
|
||||
|
||||
This component shows a CardElement component from Stripe’s React library. You can use `stripe` to be able to confirm the payment later. The `elements` variable will be used to retrieve the entered card details safely.
|
||||
|
||||
#### Implement the Workflow
|
||||
|
||||
You’ll now implement the workflow explained earlier. You’ll use Medusa’s JS Client, so make sure to import it and initialize it in your `Container` component:
|
||||
|
||||
```jsx
|
||||
import Medusa from "@medusajs/medusa-js"
|
||||
|
||||
export default function Container() {
|
||||
const client = new Medusa()
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
In your storefront, you’ll probably be managing the Medusa client through a context for better performance.
|
||||
|
||||
:::
|
||||
|
||||
Then, in the place of the `//TODO` inside the `Container` element, initialize the payment sessions and create a payment session if Stripe is available:
|
||||
|
||||
```tsx
|
||||
client.carts.createPaymentSessions(cart.id)
|
||||
.then(({ cart }) => {
|
||||
// check if stripe is selected
|
||||
const isStripeAvailable = cart.payment_sessions?.some(
|
||||
(session) => (
|
||||
session.provider_id === "stripe"
|
||||
)
|
||||
)
|
||||
if (!isStripeAvailable) {
|
||||
return
|
||||
}
|
||||
|
||||
// select stripe payment session
|
||||
client.carts.setPaymentSession(cart.id, {
|
||||
provider_id: "stripe",
|
||||
}).then(({ cart }) => {
|
||||
setClientSecret(cart.payment_session.data.client_secret)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
Notice that here it’s assumed you have access to the `cart` object throughout your storefront. Ideally, the `cart` should be managed through a context. So, every time the cart is updated, for example, when the `createPaymentSessions` or `setPaymentSession` are called, the cart should be updated in the context to be accessed from other elements. In this case, you probably wouldn’t need a `clientSecret` state variable as you can use the client secret directly from the `cart` object.
|
||||
|
||||
:::
|
||||
|
||||
Once the client secret is set, the form will be shown to the user.
|
||||
|
||||
The last step in the workflow is confirming the payment with Stripe and if it’s done successfully, completing the user’s order. This part is done in the `Form` component.
|
||||
|
||||
As you’ll use Medusa’s client again make sure to import it and initialize it:
|
||||
|
||||
```jsx
|
||||
import Medusa from "@medusajs/medusa-js"
|
||||
|
||||
export default function Form() {
|
||||
const client = new Medusa()
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Then, replace the `//TODO` in the `handlePayment` function with the following content:
|
||||
|
||||
```jsx
|
||||
return stripe.confirmCardPayment(clientSecret, {
|
||||
payment_method: {
|
||||
card: elements.getElement(CardElement),
|
||||
billing_details: {
|
||||
name,
|
||||
email,
|
||||
phone,
|
||||
address: {
|
||||
city,
|
||||
country,
|
||||
line1,
|
||||
line2,
|
||||
postal_code,
|
||||
},
|
||||
},
|
||||
},
|
||||
}).then(({ error, paymentIntent }) => {
|
||||
// TODO handle errors
|
||||
client.carts.complete(cartId).then(
|
||||
(resp) => console.log(resp)
|
||||
)
|
||||
})
|
||||
```
|
||||
|
||||
You use the `confirmCardPayment` method in the `stripe` object. You’ll need to pass it the client secret, which you can have access to from the cart object if it’s available through the context.
|
||||
|
||||
This method also requires the customer’s information like `name`, `email`, and their address. Make sure to place the values for each based on your implementation.
|
||||
|
||||
Once the promise resolves you can handle the errors, if there are any. If not, you can complete the customer’s order using `complete` from Medusa’s client. This request expects the cart ID which you should have access to as well.
|
||||
|
||||
If you run your backend and storefront now, you’ll see the Stripe UI element and you’ll be able to make orders.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Capture Payments
|
||||
|
||||
After the customer places an order, you’ll be able to see the order on the admin panel. In the payment information under the “Payment” section, you should see a “Capture” button.
|
||||
|
||||

|
||||
|
||||
Clicking this button allows you to capture the payment for an order. You can also refund payments if an order has captured payments.
|
||||
|
||||
Refunding or Capturing payments is reflected in your Stripe’s dashboard as well. This gives you access to all of Stripe’s analytical capabilities.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- Check out [more plugins](../overview.mdx) you can add to your store.
|
||||
366
docs/content/plugins/search/algolia.md
Normal file
366
docs/content/plugins/search/algolia.md
Normal file
@@ -0,0 +1,366 @@
|
||||
---
|
||||
description: 'Learn how to integrate Algolia with the Medusa backend. Learn how to install the Algolia plugin into the Medusa backend and how to integrate it into a storefront.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Algolia
|
||||
|
||||
In this document, you’ll learn how to install the [Algolia plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-algolia) and use it on both your Medusa backend and your storefront.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
[Algolia](https://www.algolia.com/) is a search engine service that allows developers to integrate advanced search functionalities into their websites including typo tolerance, recommended results, and quick responses.
|
||||
|
||||
Algolia can be used for a wide range of use cases, including ecommerce websites. By integrating Algolia into your ecommerce website, you can provide your customers with a better user experience and help them find what they’re looking for swifltly.
|
||||
|
||||
Through Medusa's flexible plugin system, it is possible to add a search engine to your Medusa backend and storefront using Algolia with just a few steps.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Components
|
||||
|
||||
It is required to have a Medusa backend installed before starting with this documentation. If not, please follow along with the [quickstart guide](../../development/backend/install.mdx) to get started in minutes.
|
||||
|
||||
Furthermore, it’s highly recommended to ensure your Medusa backend is configured to work with Redis. As Medusa uses Redis for the event queue internally, configuring Redis ensures that the search indices in Algolia are updated whenever products on the Medusa backend are updated. You can follow [this documentation to install Redis](../../development/backend/prepare-environment.mdx#redis) and then [configure it on your Medusa backend](../../development/backend/configurations.md#redis).
|
||||
|
||||
:::caution
|
||||
|
||||
If you don’t install and configure Redis on your Medusa backend, the Algolia integration will still work. However, products indexed in Algolia are only added and updated when you restart the Medusa backend.
|
||||
|
||||
:::
|
||||
|
||||
### Algolia Account
|
||||
|
||||
You need to [create an Algolia account](https://www.algolia.com/users/sign_up) before you follow this documentation. Algolia offers a free plan to get started quickly.
|
||||
|
||||
---
|
||||
|
||||
## Create an Algolia App
|
||||
|
||||
The first step is to create an Algolia app for your Medusa backend. To create one, open the [Applications page](https://www.algolia.com/account/applications) or, on your dashboard, go to Settings then choose Applications.
|
||||
|
||||
On the Applications page, click on the New application button at the top right.
|
||||
|
||||

|
||||
|
||||
In the new page that opens, optionally enter a name for the application and choose a subscription plan. You can choose the Free plan for now, but it’s recommended to switch to the Pay-as-you-go plan as your business grows.
|
||||
|
||||

|
||||
|
||||
Once you’re done, click on the Next Step button. If you picked Pay as you go service, you’ll need to enter billing details before you proceed.
|
||||
|
||||
Then, you’ll be asked to pick a region for your application. Once you’re done, click on Review Application Details.
|
||||
|
||||

|
||||
|
||||
In the last step, you’ll see a summary of your order. If all looks good, check the checkboxes at the end of the form to indicate that you agree to the terms and conditions. Then, click on the Create Application button.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Retrieve API Keys
|
||||
|
||||
To retrieve the API keys that you’ll use in the next sections, go to Settings, then choose API Keys in the Team and Access section.
|
||||
|
||||

|
||||
|
||||
On this page, you’ll find the Application ID, Search-Only API Key, and Admin API Key. You’ll need the Application ID and Admin API Key for the Medusa backend. As for the storefront, you’ll need the Application ID and Search-Only API Key.
|
||||
|
||||
:::note
|
||||
|
||||
If you have more than one application in your Algolia account, make sure you’re viewing the keys of the correct application by checking the Application dropdown at the top left.
|
||||
|
||||
:::
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Install the Algolia Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the Algolia plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-algolia
|
||||
```
|
||||
|
||||
Then, add the following environment variables to your Medusa backend:
|
||||
|
||||
```bash
|
||||
ALGOLIA_APP_ID=<YOUR_APP_ID>
|
||||
ALGOLIA_ADMIN_API_KEY=<YOUR_ADMIN_API_KEY>
|
||||
```
|
||||
|
||||
Where `<YOUR_APP_ID>` and `<YOUR_ADMIN_API_KEY>` are respectively the Application ID and Admin API Key found on the [API Keys page](#retrieve-api-keys).
|
||||
|
||||
Finally, in `medusa-config.js` add the following item into the `plugins` array:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-plugin-algolia`,
|
||||
options: {
|
||||
application_id: process.env.ALGOLIA_APP_ID,
|
||||
admin_api_key: process.env.ALGOLIA_ADMIN_API_KEY,
|
||||
settings: {
|
||||
products: {
|
||||
searchableAttributes: ["title", "description"],
|
||||
attributesToRetrieve: [
|
||||
"id",
|
||||
"title",
|
||||
"description",
|
||||
"handle",
|
||||
"thumbnail",
|
||||
"variants",
|
||||
"variant_sku",
|
||||
"options",
|
||||
"collection_title",
|
||||
"collection_handle",
|
||||
"images",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
The `searchableAttributes` are the attributes in a product that are searchable, and `attributesToRetrieve` are the attributes to retrieve for each product result. You’re free to make changes to these attributes as you see fit, but these are the recommended attributes.
|
||||
|
||||
---
|
||||
|
||||
## Test the Algolia Plugin
|
||||
|
||||
Run your Medusa backend with the following command:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run start
|
||||
```
|
||||
|
||||
The quickest way to test that the integration is working is by sending a `POST` request to `/store/products/search`. This endpoint accepts a `q` body parameter of the query to search for and returns in the result the products that match this query.
|
||||
|
||||

|
||||
|
||||
You can also check that the products are properly indexed by opening your Algolia dashboard and choosing Search from the left sidebar. You’ll find your products that are on your Medusa backend added there.
|
||||
|
||||
:::note
|
||||
|
||||
If you have more than one application on your Algolia account, make sure you’re viewing the keys of the correct one by checking the Application dropdown at the top left.
|
||||
|
||||
:::
|
||||
|
||||

|
||||
|
||||
### Add or Update Products
|
||||
|
||||
If you add or update products on your Medusa backend, the addition or update will be reflected in the Algolia indices.
|
||||
|
||||
:::note
|
||||
|
||||
This feature is only available if you have Redis installed and configured with your Medusa backend as mentioned in the [Prerequisites section](#prerequisites). Otherwise, you must re-run the Medusa backend to see the change in the Algolia indices.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Add Search to your Storefront
|
||||
|
||||
In this section, you’ll learn how to add the UI on your storefront to allow searching with Algolia. This section has instructions for Medusa’s [Next.js](../../starters/nextjs-medusa-starter.mdx) storefront as well as React-based frameworks such as the [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefront.
|
||||
|
||||
### Storefront Prerequisites
|
||||
|
||||
It is assumed you already have a storefront set up and working with the Medusa backend, as this section only covers how to add the search UI.
|
||||
|
||||
:::tip
|
||||
|
||||
If you don’t have a storefront set up, you can use the [Gatsby](../../starters/gatsby-medusa-starter.mdx) or [Next.js](../../starters/nextjs-medusa-starter.mdx) storefronts Medusa provides.
|
||||
|
||||
:::
|
||||
|
||||
### Add to Next.js Storefront
|
||||
|
||||
The Next.js storefront has the Algolia integration available out of the box. To get it working, you just need to follow three steps.
|
||||
|
||||
First, ensure that the search feature is enabled in `store.config.json`:
|
||||
|
||||
```json title=store.config.json
|
||||
{
|
||||
"features": {
|
||||
"search": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then, add the necessary environment variables:
|
||||
|
||||
```bash
|
||||
NEXT_PUBLIC_SEARCH_APP_ID=<YOUR_APP_ID>
|
||||
NEXT_PUBLIC_SEARCH_API_KEY=<YOUR_SEARCH_API_KEY>
|
||||
NEXT_PUBLIC_SEARCH_INDEX_NAME=products
|
||||
```
|
||||
|
||||
Where `<YOUR_APP_ID>` and `<YOUR_SEARCH_API_KEY>` are respectively the Application ID and Search-Only API Key on the [API Keys page](#retrieve-api-keys).
|
||||
|
||||
Finally, change the code in `src/lib/search-client.ts` to the following:
|
||||
|
||||
```jsx title=src/lib/search-client.ts
|
||||
import algoliasearch from "algoliasearch/lite"
|
||||
|
||||
const appId = process.env.NEXT_PUBLIC_SEARCH_APP_ID || ""
|
||||
|
||||
const apiKey =
|
||||
process.env.NEXT_PUBLIC_SEARCH_API_KEY || "test_key"
|
||||
|
||||
export const searchClient = algoliasearch(appId, apiKey)
|
||||
|
||||
export const SEARCH_INDEX_NAME =
|
||||
process.env.NEXT_PUBLIC_INDEX_NAME || "products"
|
||||
```
|
||||
|
||||
If you run your Next.js storefront now while the Medusa backend is running, the search functionality will be available in your storefront.
|
||||
|
||||
:::note
|
||||
|
||||
To make sure the Next.js storefront properly displays the products in the search result, include in the `attributesToRetrieve` setting of the Algolia plugin on the Medusa backend at least the fields `title`, `handle`, `description`, and `thumbnail`.
|
||||
|
||||
:::
|
||||
|
||||

|
||||
|
||||
### Add to Gatsby and React-Based Storefronts
|
||||
|
||||
This section covers adding the search UI to React-based storefronts. It uses the Gatsby storefront as an example, but you can use the same steps on any React-based framework.
|
||||
|
||||
:::tip
|
||||
|
||||
For other frontend frameworks, please check out [Algolia’s Integrations guide](https://www.algolia.com/developers/?ui-libraries&client-libraries) for steps based on your framework.
|
||||
|
||||
:::
|
||||
|
||||
In the directory that contains your storefront, run the following command to install the necessary dependencies:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install algoliasearch react-instantsearch-dom
|
||||
```
|
||||
|
||||
Then, add the following environment variables:
|
||||
|
||||
```bash
|
||||
GATSBY_ALGOLIA_APP_ID=<YOUR_APP_ID>
|
||||
GATSBY_ALGOLIA_SEARCH_API_KEY=<YOUR_SEARCH_API_KEY>
|
||||
GATSBY_SEARCH_INDEX_NAME=products
|
||||
```
|
||||
|
||||
Where `<YOUR_APP_ID>` and `<YOUR_SEARCH_API_KEY>` are respectively the Application ID and Search-Only API Key on the [API Keys page](#retrieve-api-keys).
|
||||
|
||||
:::note
|
||||
|
||||
In Gatsby, environment variables that should be public and available in the browser are prefixed with `GATSBY_`. If you’re using another React-based framework, you might need to use a different prefix to ensure these variables can be used in your code. Please refer to your framework’s documentation for help on this.
|
||||
|
||||
:::
|
||||
|
||||
Then, create the file `src/components/header/search.jsx` with the following content:
|
||||
|
||||
```jsx title=src/components/header/search.jsx
|
||||
import {
|
||||
Highlight,
|
||||
Hits,
|
||||
InstantSearch,
|
||||
SearchBox,
|
||||
connectStateResults,
|
||||
} from "react-instantsearch-dom"
|
||||
|
||||
import React from "react"
|
||||
import algoliasearch from "algoliasearch/lite"
|
||||
|
||||
const searchClient = algoliasearch(
|
||||
process.env.GATSBY_ALGOLIA_APP_ID,
|
||||
process.env.GATSBY_ALGOLIA_SEARCH_API_KEY
|
||||
)
|
||||
|
||||
const Search = () => {
|
||||
const Results = connectStateResults(
|
||||
({ searchState, searchResults, children }) => {
|
||||
return (
|
||||
searchState && searchState.query &&
|
||||
searchResults && searchResults.nbHits !== 0 ?
|
||||
(
|
||||
<div
|
||||
className="absolute ...">
|
||||
{children}
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<InstantSearch
|
||||
indexName={process.env.GATSBY_SEARCH_INDEX_NAME}
|
||||
searchClient={searchClient}>
|
||||
<SearchBox submit={null} reset={null} />
|
||||
<Results>
|
||||
<Hits hitComponent={Hit} />
|
||||
</Results>
|
||||
</InstantSearch>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Hit = ({ hit }) => {
|
||||
return (
|
||||
<div key={hit.id} className="relative">
|
||||
<div className="hit-name">
|
||||
<Highlight attribute="title" hit={hit} tagName="mark" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Search
|
||||
```
|
||||
|
||||
This file uses the dependencies you installed to show the search results. It also initializes Algolia using the environment variables you added.
|
||||
|
||||
:::note
|
||||
|
||||
If you named your environment variables differently based on your framework, make sure to rename them here as well.
|
||||
|
||||
:::note
|
||||
|
||||
Finally, import this file at the beginning of `src/components/header/index.jsx`:
|
||||
|
||||
```jsx title=src/components/header/index.jsx
|
||||
import Search from "./search"
|
||||
```
|
||||
|
||||
And add the `Search` component in the returned JSX before `RegionPopover`:
|
||||
|
||||
```jsx title=src/components/header/index.jsx
|
||||
// ...
|
||||
<div className="...">
|
||||
<Search />
|
||||
<RegionPopover regions={mockData.regions} />
|
||||
</div>
|
||||
// ...
|
||||
```
|
||||
|
||||
If you run your Gatsby storefront while the Medusa backend is running, you should find a search bar in the header of the page. Try entering a query to search through the products in your store.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Deploy your Medusa backend](../../deployments/server/index.mdx)
|
||||
- [Deploy your Gatsby storefront](../../deployments/storefront/deploying-gatsby-on-netlify.md)
|
||||
5
docs/content/plugins/search/index.mdx
Normal file
5
docs/content/plugins/search/index.mdx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Search Plugins
|
||||
|
||||
<DocCardList />
|
||||
332
docs/content/plugins/search/meilisearch.md
Normal file
332
docs/content/plugins/search/meilisearch.md
Normal file
@@ -0,0 +1,332 @@
|
||||
---
|
||||
description: 'Learn how to integrate MeiliSearch with the Medusa backend. Learn how to install the MeiliSearch plugin on the Medusa backend and integrate it into the storefront.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# MeiliSearch
|
||||
|
||||
In this document, you’ll learn how to install the [MeiliSearch plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-meilisearch) and use it on both your Medusa Backend and your storefront.
|
||||
|
||||
## Overview
|
||||
|
||||
[MeiliSearch](https://www.meilisearch.com/) is a super-fast, open source search engine built in Rust. It comes with a wide range of features including typo-tolerance, filtering, and sorting.
|
||||
|
||||
MeiliSearch also provides a pleasant developer experience, as it is extremely intuitive and newcomer-friendly. So, even if you're new to the search engine ecosystem, [their documentation](https://docs.meilisearch.com/) is resourceful enough for everyone to go through and understand.
|
||||
|
||||
Through Medusa's flexible plugin system, it is possible to add a search engine to your Medusa backend and storefront using MeiliSearch with just a few steps.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Components
|
||||
|
||||
It is required to have a Medusa backend installed before starting with this documentation. If not, please follow along with the [quickstart guide](../../development/backend/install.mdx) to get started in minutes.
|
||||
|
||||
Furthermore, it’s highly recommended to ensure your Medusa backend is configured to work with Redis. As Medusa uses Redis for the event queue internally, configuring Redis ensures that the search indices in MeiliSearch are updated whenever products on the Medusa backend are updated. You can follow [this documentation to install Redis](../../development/backend/prepare-environment.mdx#redis) and then [configure it on your Medusa backend](../../development/backend/configurations.md#redis).
|
||||
|
||||
:::caution
|
||||
|
||||
If you don’t install and configure Redis on your Medusa backend, the MeiliSearch integration will still work. However, products indexed in MeiliSearch are only added and updated when you restart the Medusa backend.
|
||||
|
||||
:::
|
||||
|
||||
### MeiliSearch Instance
|
||||
|
||||
You must install MeiliSearch to use it with Medusa. You can follow [this documentation to install MeiliSearch](https://docs.meilisearch.com/learn/getting_started/quick_start.html#setup-and-installation) either locally or on a cloud.
|
||||
|
||||
Furthermore, you should create a master key for your MeiliSearch instance. If you don’t have one created, follow [this guide](https://docs.meilisearch.com/learn/security/master_api_keys.html#protecting-a-meilisearch-instance) to create a master key.
|
||||
|
||||
---
|
||||
|
||||
## Install the MeiliSearch Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the MeiliSearch plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-meilisearch
|
||||
```
|
||||
|
||||
Then, add the following environment variables to your Medusa backend:
|
||||
|
||||
```bash
|
||||
MEILISEARCH_HOST=<YOUR_MEILISEARCH_HOST>
|
||||
MEILISEARCH_API_KEY=<YOUR_MASTER_KEY>
|
||||
```
|
||||
|
||||
Where `<YOUR_MEILISEARCH_HOST>` is the host of your MeiliSearch instance. By default, if MeiliSearch is installed locally, the host is `http://127.0.0.1:7700`.
|
||||
|
||||
`<YOUR_MASTER_KEY>` is the master key of your MeiliSearch instance.
|
||||
|
||||
Finally, in `medusa-config.js` add the following item into the `plugins` array:
|
||||
|
||||
```jsx title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-plugin-meilisearch`,
|
||||
options: {
|
||||
// config object passed when creating an instance
|
||||
// of the MeiliSearch client
|
||||
config: {
|
||||
host: process.env.MEILISEARCH_HOST,
|
||||
apiKey: process.env.MEILISEARCH_API_KEY,
|
||||
},
|
||||
settings: {
|
||||
// index name
|
||||
products: {
|
||||
// MeiliSearch's setting options
|
||||
// to be set on a particular index
|
||||
searchableAttributes: [
|
||||
"title",
|
||||
"description",
|
||||
"variant_sku",
|
||||
],
|
||||
displayedAttributes: [
|
||||
"title",
|
||||
"description",
|
||||
"variant_sku",
|
||||
"thumbnail",
|
||||
"handle",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
You can change the `searchableAttributes` and `displayedAttributes` as you see fit. However, the attributes included are the recommended attributes.
|
||||
|
||||
---
|
||||
|
||||
## Test MeiliSearch Plugin
|
||||
|
||||
Make sure your MeiliSearch instance is running. If you’re unsure how to run it, you can check the [installation documentation](https://docs.meilisearch.com/learn/getting_started/quick_start.html#setup-and-installation) for the command to run the MeiliSearch instance.
|
||||
|
||||
Then, run the Medusa backend:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run start
|
||||
```
|
||||
|
||||
The quickest way to test that the integration is working is by sending a `POST` request to `/store/products/search`. This endpoint accepts a `q` body parameter of the query to search for and returns in the result the products that match this query.
|
||||
|
||||

|
||||
|
||||
You can also check that the products are properly indexed by opening the MeiliSearch host URL in your browser, which is `http://127.0.0.1:7700/` by default. You’ll find your products that are on your Medusa backend added there.
|
||||
|
||||

|
||||
|
||||
### Add or Update Products
|
||||
|
||||
If you add or update products on your Medusa backend, the addition or update will be reflected in the MeiliSearch indices.
|
||||
|
||||
:::note
|
||||
|
||||
This feature is only available if you have Redis installed and configured with your Medusa backend as mentioned in the [Prerequisites section](#prerequisites). Otherwise, you must re-run the Medusa backend to see the change in the MeiliSearch indices.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Add Search to your Storefront
|
||||
|
||||
In this section, you’ll learn how to add the UI on your storefront to allow searching with MeiliSearch. This section has instructions for Medusa’s [Next.js](../../starters/nextjs-medusa-starter.mdx) storefront as well as React-based frameworks such as the [Gatsby storefront](../../starters/gatsby-medusa-starter.mdx).
|
||||
|
||||
### Storefront Prerequisites
|
||||
|
||||
It is assumed you already have a storefront set up and working with the Medusa backend, as this section only covers how to add the search UI.
|
||||
|
||||
:::tip
|
||||
|
||||
If you don’t have a storefront set up, you can use the [Gatsby](../../starters/gatsby-medusa-starter.mdx) or [Next.js](../../starters/nextjs-medusa-starter.mdx) storefronts Medusa provides.
|
||||
|
||||
:::
|
||||
|
||||
Furthermore, you must create an API key in your MeiliSearch instance that will be used to search on the storefront. To do that, run the following command in your terminal while the MeiliSearch instance is running:
|
||||
|
||||
```bash
|
||||
curl \
|
||||
-X POST '<MEILISEARCH_HOST>/keys' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer <MEILISEARCH_MASTER_KEY>' \
|
||||
--data-binary '{
|
||||
"description": "Search products",
|
||||
"actions": ["search"],
|
||||
"indexes": ["products"],
|
||||
"expiresAt": "2024-01-01T00:00:00Z"
|
||||
}'
|
||||
```
|
||||
|
||||
Make sure to replace `<MEILISEARCH_HOST>` and `<MEILISEARCH_MASTER_KEY>` accordingly.
|
||||
|
||||
If this request is successful, the API key will be available under the `key` property returned in the JSON response.
|
||||
|
||||
### Add to Next.js Storefront
|
||||
|
||||
The Next.js storefront has the MeiliSearch integration available out of the box. To get it working, you just need to follow two steps.
|
||||
|
||||
First, ensure that the search feature is enabled in `store.config.json`:
|
||||
|
||||
```json title=store.config.json
|
||||
{
|
||||
"features": {
|
||||
"search": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then, add the necessary environment variables:
|
||||
|
||||
```bash
|
||||
NEXT_PUBLIC_SEARCH_ENDPOINT=<YOUR_MEILISEARCH_HOST>
|
||||
NEXT_PUBLIC_SEARCH_API_KEY=<YOUR_API_KEY>
|
||||
NEXT_PUBLIC_SEARCH_INDEX_NAME=products
|
||||
```
|
||||
|
||||
Make sure to replace `<YOUR_MEILISEARCH_HOST>` with your MeiliSearch host and `<YOUR_API_KEY>` with the API key you created as instructed in the [Storefront Prerequisites](#storefront-prerequisites) section.
|
||||
|
||||
If you run your Next.js storefront now while the Medusa backend and the MeiliSearch services are running, the search functionality will be available in your storefront.
|
||||
|
||||
:::note
|
||||
|
||||
To make sure the Next.js storefront properly displays the products in the search result, include in the `displayedAttributes` setting of the MeiliSearch plugin on the Medusa backend at least the fields `title`, `handle`, `description`, and `thumbnail`.
|
||||
|
||||
:::
|
||||
|
||||

|
||||
|
||||
### Add to Gatsby and React-Based Storefronts
|
||||
|
||||
This section covers adding the search UI to React-based storefronts. It uses the Gatsby storefront as an example, but you can use the same steps on any React-based framework.
|
||||
|
||||
:::tip
|
||||
|
||||
For other frontend frameworks, please check out [MeiliSearch’s Integrations guide](https://github.com/meilisearch/integration-guides) for steps based on your framework.
|
||||
|
||||
:::
|
||||
|
||||
In the directory that contains your storefront, run the following command to install the necessary dependencies:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install react-instantsearch-dom @meilisearch/instant-meilisearch
|
||||
```
|
||||
|
||||
Then, add the following environment variables:
|
||||
|
||||
```bash
|
||||
GATSBY_MEILISEARCH_HOST=<YOUR_MEILISEARCH_HOST>
|
||||
GATSBY_MEILISEARCH_API_KEY=<YOUR_API_KEY>
|
||||
GATSBY_SEARCH_INDEX_NAME=products
|
||||
```
|
||||
|
||||
Make sure to replace `<YOUR_MEILISEARCH_HOST>` with your MeiliSearch host and `<YOUR_API_KEY>` with the API key you created as instructed in the [Storefront Prerequisites](#storefront-prerequisites) section.
|
||||
|
||||
:::caution
|
||||
|
||||
In Gatsby, environment variables that should be public and available in the browser are prefixed with `GATSBY_`. If you’re using another React-based framework, you might need to use a different prefix to ensure these variables can be used in your code. Please refer to your framework’s documentation for help on this.
|
||||
|
||||
:::
|
||||
|
||||
Then, create the file `src/components/header/search.jsx` with the following content:
|
||||
|
||||
```jsx title=src/components/header/search.jsx
|
||||
import {
|
||||
Highlight,
|
||||
Hits,
|
||||
InstantSearch,
|
||||
SearchBox,
|
||||
connectStateResults,
|
||||
} from "react-instantsearch-dom"
|
||||
|
||||
import React from "react"
|
||||
import {
|
||||
instantMeiliSearch,
|
||||
} from "@meilisearch/instant-meilisearch"
|
||||
|
||||
const searchClient = instantMeiliSearch(
|
||||
process.env.GATSBY_MEILISEARCH_HOST,
|
||||
process.env.GATSBY_MEILISEARCH_API_KEY
|
||||
)
|
||||
|
||||
const Search = () => {
|
||||
const Results = connectStateResults(
|
||||
({ searchState, searchResults, children }) => {
|
||||
return (
|
||||
searchState && searchState.query &&
|
||||
searchResults && searchResults.nbHits !== 0 ?
|
||||
(
|
||||
<div
|
||||
className="absolute ...">
|
||||
{children}
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<InstantSearch
|
||||
indexName={process.env.GATSBY_SEARCH_INDEX_NAME}
|
||||
searchClient={searchClient}>
|
||||
<SearchBox submit={null} reset={null} />
|
||||
<Results>
|
||||
<Hits hitComponent={Hit} />
|
||||
</Results>
|
||||
</InstantSearch>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Hit = ({ hit }) => {
|
||||
return (
|
||||
<div key={hit.id} className="relative">
|
||||
<div className="hit-name">
|
||||
<Highlight attribute="title" hit={hit} tagName="mark" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Search
|
||||
```
|
||||
|
||||
This file uses the dependencies you installed to show the search results. It also initializes MeiliSearch using the environment variables you added.
|
||||
|
||||
:::caution
|
||||
|
||||
If you named your environment variables differently based on your framework, make sure to rename them here as well.
|
||||
|
||||
:::
|
||||
|
||||
Finally, import this file at the beginning of `src/components/header/index.jsx`:
|
||||
|
||||
```jsx title=src/components/header/index.jsx
|
||||
import Search from "./search"
|
||||
```
|
||||
|
||||
And add the `Search` component in the returned JSX before `RegionPopover`:
|
||||
|
||||
```jsx title=src/components/header/index.jsx
|
||||
// ...
|
||||
<div className="...">
|
||||
<Search />
|
||||
<RegionPopover regions={mockData.regions} />
|
||||
</div>
|
||||
// ...
|
||||
```
|
||||
|
||||
If you run your Gatsby storefront while the Medusa backend and the MeiliSearch instance are running, you should find a search bar in the header of the page. Try entering a query to search through the products in your store.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Deploy your Medusa backend](../../deployments/server/index.mdx).
|
||||
- [Deploy your Gatsby storefront](../../deployments/storefront/deploying-gatsby-on-netlify.md).
|
||||
Reference in New Issue
Block a user