# Connected content

Connected content is a feature in [Liquid templates](/product/personalization/liquid-templates/) that allows you to dynamically retrieve and use data from an external source, such as a web service, directly within your email or push notification messages. This feature enables real-time personalization by fetching JSON data from a specified URL and saving it to a variable that can be utilized in your content. 

## Key use cases

- **Product recommendations**: Display personalized product lists tailored to each user.

- **Promo codes**: Insert unique promo codes generated by a backend service.

## Prerequisites

* To use Connected Content, you must have your own backend service that generates and provides the required data (e.g., promo codes, product recommendations) based on **User ID, HWID, or custom tags**. Pushwoosh then fetches this data before sending a message.

## Step-by-step implementation guide

<Aside type="caution" icon="setting" title="Developer assistance needed">
You'll need your developer team's help to use Connected content. Share this guide with them to get started.
</Aside>

### Step 1. Set up backend service 

The backend service should:

* Accept a request containing user-specific parameters (e.g., `userId`). Connected Content supports `UserID`, `HWID`, or any custom tags you’ve set up in your project.  
* Return a JSON response with the required data. This content can then be inserted dynamically into messages

<Aside type="note" title="How it works"> 

The backend service acts as a data provider, responding to HTTP requests with user-specific information. 

1. Pushwoosh sends a request to your backend, passing user-specific identifiers as query parameters.  
2. Your backend processes the request and retrieves the requested data.  
3. Your backend returns a JSON response.  
4. Before sending a message, Pushwoosh fetches the JSON response from the backend service and uses the returned values (e.g., the `code`) in the message content dynamically.

**Example response**

```
{ "code": "SPECIALOFFERFORUSER12345" }
```
</Aside>



### Step 2. Create a preset with Connected content in Pushwoosh
 
1. In the [Push](/product/content/push-presets/) or [Email content editor](/product/content/email-content/drag-and-drop-email-editor/), insert the Connected Content syntax into the message field.

**Example** 

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }} :save result %}  
```
**Syntax breakdown**
|  |  |
| ----- | ----- |
| `connected_content` | Fetches JSON data from the specified backend URL. |
|    `http://your-backend-url.com` | The backend endpoint that returns required data in JSON format. |
| `userId={{ ${userid} }}` | A dynamic query parameter that passes the user ID to the backend. Inside `connected_content`, wrap a variable in `${}`. In the message text, write `{{userid}}` without it. |
| `:save result` | Stores the fetched JSON response in the result variable for use in Liquid templates |

![Insert the Connected Content syntax](/connectedcontent.webp)

**Authentication (optional)**

If your backend service requires authentication, you can include an API key or token in the Connected Content request to ensure secure access. 

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }}&auth=YOUR_API_KEY :save result %}  
```

You can also send authentication (or any other) data as HTTP headers using the optional `:headers` parameter — a JSON object of header names and values.

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }} :headers {"Authorization": "Bearer YOUR_TOKEN", "X-Api-Key": "YOUR_API_KEY"} :save result %}  
```
|  |  |
| ----- | ----- |
| `:headers {...}` | A JSON object of HTTP headers sent with the request, e.g. `Authorization: Bearer <token>`. |

<Aside type="caution" title="Static values only">
`${}` personalization variables work only inside the URL. Values inside `:headers` are static and are not interpolated.
</Aside>

<Aside type="danger" title="Keep credentials out of the URL">
Prefer `:headers` over a URL query parameter (e.g. `&auth=YOUR_API_KEY`) for API keys and tokens: if the fetch fails, the request URL is written to logs, exposing a key placed there. Values inside `:headers` are never logged.

Connected content also requires Liquid content templates to be enabled for your account. If they aren't, the whole `connected_content` tag — including any key inside it — is sent to every recipient as literal text instead of being rendered. Contact [Pushwoosh Support](https://help.pushwoosh.com/hc/en-us/requests/new) if you're unsure whether your account has this enabled.
</Aside>

**Using tags in Connected content**

To include a tag value, add it to the URL as a query parameter in the same `{{ ${tag_name} }}` form. Written as `{{ tag_name }}` inside the `connected_content` tag, the value is sent empty.

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }}&lang={{ ${Language} }} :save result %} 
```

2. Next, add the message text incorporating the **retrieved data**, like this:

```

Hey, {{userid}}, grab your personal promo code - {{result.code}} 
```

![Add the message text with the **retrieved data**](/connectedcontent-1.webp)

3. After finalizing the message content and configuring the preset settings, save it for reuse in campaigns.

<video src="/connectedcontent-2.webm" title="Send a message with connected content" autoplay loop muted playsinline />

### Step 3. Send a message using the configured preset 

Send a message with this preset using the [one-time push](/product/messaging-channels/push-notifications/send-push-notifications/one-time-push/#how-to-send-a-push-notification-using-the-one-time-push-form) or [email form](/product/messaging-channels/emails/sending-emails/send-one-time-emails/) or [customer journey](/product/customer-journey/pushwoosh-journey-overview/). 

<Aside type="caution" title="Important">
If the service returns a status other than HTTP 200 OK, the email or push notification will not be sent. This ensures that your communication only goes out if the necessary data is successfully retrieved.
</Aside>