# In-app editor blocks reference

Reference for every block you can add on the [built-in editor](/product/content/in-apps/no-code-in-app-editor/create-rich-media-in-the-built-in-editor/) canvas.

Each block type serves a different purpose in the message:

* **[Heading](#heading-and-text):** titles and short headlines
* **[Text](#heading-and-text):** body copy and longer descriptions
* **[Button](#button):** a tappable call to action
* **[Image](#image):** pictures from [Media store](/product/content/media-store/), upload, or URL
* **[Video](#video):** a tappable video thumbnail that opens a YouTube or Vimeo video
* **[Card](#card):** an image with heading, text, and button in one layout
* **[Divider](#divider):** a line that separates sections
* **[Columns](#columns):** side-by-side layouts (2, 3, or 4 equal columns, or 33/67 and 67/33 splits)
* **[Timer](#countdown-timer):** a countdown for offers and deadlines
* **[Menu](#menu):** a row or column of navigation or contact links
* **[Social](#social):** icons that link to your social profiles
* **[HTML](#html):** custom HTML, such as a form, survey, or embedded video
* **[Products](#products):** a grid of product cards from your [Product Catalog](/product/content/product-catalog/) or a user's abandoned cart

## How to configure editor blocks

Drag a block onto the canvas from the **Blocks** tab, or click it to add it at the end. Select the block to open its settings in the right panel and configure content, links, size, and spacing.

<Aside type="tip">
Every block also has **Visibility** and **Display condition** settings. Use them to hide a block on phone or desktop, or show it only to specific users. [Learn more](/product/content/in-apps/no-code-in-app-editor/show-in-app-content-to-specific-users/)
</Aside>

### Heading and text

**Heading** and **Text** blocks hold the copy users read in the in-app message. Edit the text on the canvas and format it with the toolbar.

Click a **Heading** or **Text** block to edit its copy on the canvas. Select some text to bring up the formatting toolbar: bold, italic, underline, alignment, a link button, and a **text style** dropdown.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-8.webp" alt="Heading block selected on the canvas with the text formatting toolbar showing style and formatting options"/>

Merge Tags are placeholders that insert a [Tag](/product/audience-data-and-segmentation/user-data-tags/tags/) value from the user's profile into the message, so each subscriber sees personalized copy. To add one, select the text, click **Merge Tags** in the toolbar, and choose a Tag from your account. [Learn more about personalized in-app messages](/product/how-to-guides/how-to-send-a-personalized-message/how-to-send-a-personalized-in-app-message/)


### Image

An **Image** block displays a picture in the in-app template. 

<img src="/rich-media-create-rich-media-in-the-built-in-editor-40.webp" alt="Image block on the canvas with Image settings showing Replace image, Image URL, Alt text, Generate alt with AI, Prompt, Width, Height, Corner radius, and Alignment" width="600"/>


Select it on the canvas to open the **Image** settings in the right panel.

* **Add image** / **Replace image:** click **Add image** when the block is empty, or **Replace image** when a picture is already set. You can upload a file or pick one from your [Media store](/product/content/media-store/).
* **Image URL:** paste a hosted link to the image.
* **Alt text:** describe the image for accessibility.
* **Prompt:** the AI generation prompt for an image you created with **Generate with AI**.
* **Width (px)** / **Height (px):** fix the image to a pixel size. Leave a field empty for it to size automatically.
* **Corner radius (px):** round the image's corners.
* **Alignment:** left, center, or right.

In **Link**, set an **Action Type** (for example **Open Website** or **URL or Deeplink**) and its **URL** to open something when the image is tapped, and a **Link target** to open it in the same tab or a new one.

In **Spacing**, turn on **Padding** to add space around the image. Use **All sides** for the same padding on every side, or turn on **More options** to set each side separately.

### Video

A **Video** block adds a YouTube or Vimeo video to the message as a tappable thumbnail. The message shows a still image with a ▶ overlay. Tapping it opens the video in the YouTube or Vimeo app or browser.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-38.webp" alt="Video block on the canvas with Video settings showing Video URL, Alt text, Replace thumbnail, Thumbnail URL, and Play button overlay" width="600"/>

Select the block on the canvas to open its settings:

* **Video URL:** paste a YouTube or Vimeo link. The editor fetches a thumbnail automatically.
* **Alt text:** describe the video for accessibility.
* **Thumbnail URL:** keep the auto-fetched thumbnail, or click **Add thumbnail** / **Replace thumbnail** to pick one from [Media store](/product/content/media-store/), or paste a hosted link directly.
* **Play button overlay:** on by default. Turn off to show the plain thumbnail without the ▶ overlay.
* **Width (px)**, **Corner radius (px)**, and **Alignment:** control how the thumbnail looks and where it sits in the layout.


### Card

A **Card** block pairs an image with a heading, text, and button in a single ready-made layout, so you don't have to place and align four separate blocks by hand.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-37.webp" alt="Card block on the canvas with Card settings showing Layout, Replace image, Image URL, Alt text, Prompt, Padding, and Corner radius" width="600"/>

* **Layout:** choose which side the image sits on relative to the content, or turn on **Wrap text around image**.
* **Image:** add or replace the image, set alt text, edit the AI generation **Prompt**, add **Padding**, and set **Corner radius (px)**.
* **Size & fit:** set the image's **Width**, **Height**, **Crop** (Original or a fixed ratio), and **Fit** (Cover or a focal point). The exact fields depend on the **Layout** you picked.
* **Link:** make the whole card open a URL when tapped.

Edit the card's heading, text, and button the same way you edit the standalone [Heading, Text](#heading-and-text), and [Button](#button) blocks.

### Button

A **Button** is a tappable call to action in the in-app message. Use it to open a URL, run custom JavaScript, or close the message.

Click a **Button** block to edit its label on the canvas. Use the toolbar to change font size, text color, bold, italic, underline, and alignment.

To set what happens when the user taps the button:

1. Click the link icon in the toolbar to open **Insert/Edit Link**.
2. Choose an **Action type**: **Open Website**, **URL or Deeplink**, or **Custom Javascript**.
3. Fill in the fields for that action (see below).
4. Click **Save**.

#### Open Website

**Open Website** opens a web page when the user taps the button. Enter the address in **URL**, for example `https://example.com`.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-10.webp" alt="Insert Edit Link dialog for a Button with Action type Open Website and a URL field"/>

#### URL or Deeplink

**URL or Deeplink** opens a link or deep link when the user taps the button. Enter the address in **URL**, for example an app screen: `myapp://screen`.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-45.webp" alt="Button toolbar with Insert Edit Link dialog open, Action type URL or Deeplink, and URL set to myapp://screen"/>

#### Run custom JavaScript

**Custom Javascript** runs code when the user taps the button. Enter the code in the **onClick** field.

Use it when a tap should do something in Pushwoosh, not only open a link. The person in the app still sees a normal button. They do not see tags or events. You decide what happens next on screen: leave the message open, or close it in the same **onClick**.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-11.webp" alt="Insert Edit Link dialog for a Button with Action type Custom Javascript and onClick set to closeInApp"/>

**Available methods in onClick**

* `pushwoosh.closeInApp()`: close the in-app message. Omit it to keep the message open after the tap.
* `pushwoosh.sendTags({...})`: save values as [device tags](/product/audience-data-and-segmentation/user-data-tags/tags/) for later campaigns.
* `pushwoosh.postEvent(...)`: send a [custom event](/product/audience-data-and-segmentation/events/custom-events/), for example to start a Customer Journey.
* `pushwoosh.getTags(...)`: read current tags. Useful in custom HTML to change what the message shows.
* `pushwoosh.getCustomData()`: read custom data passed from the push that opened this in-app.

##### Example: let users pick an interest and save it for later campaigns

1. Add a question in a **Text** or **Heading** block, for example: "Which sport are you into?"
2. Add one **Button** per option, for example: **Yoga** and **Gym**.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-12.webp" alt="In-app template with Yoga and Gym buttons and Custom Javascript onClick for the Yoga button"/>

3. Set **Action type** to **Custom Javascript** for each button.
4. For the **Yoga** button, paste this into **onClick**:

```js
pushwoosh.sendTags({ interest: "yoga" });
pushwoosh.closeInApp();
```

5. For the **Gym** button, paste this into **onClick**:

```js
pushwoosh.sendTags({ interest: "gym" });
pushwoosh.closeInApp();
```


When the user taps **Yoga**, Pushwoosh writes the `interest` tag on their device and closes the in-app. You can then target that user in a [segment](/product/audience-data-and-segmentation/segmentation/) or [Customer Journey](/product/customer-journey/journey-elements/#in-app).

<LinkCard title="Learn more about how to create in-apps with JavaScript" href="/developer/guides/messaging-channels/inapp-with-javascript/" />

### Divider

A **Divider** is a horizontal line between content blocks. Use it to separate sections visually in the template.

Configure **line style** (Solid, Dashed, Dotted), **color**, **thickness**, and **width** in the settings panel.

### HTML

The **HTML** block lets you paste custom HTML into an in-app template. Use it for a custom form, survey, or embedded video when there is no dedicated Form block for in-app messages.


##### Examples

The examples below show common ways to use the HTML block in an in-app template: a lead form, a survey, and an embedded video.

<Aside type="note">
The form and survey examples save device tags and send events through Pushwoosh. Create the custom events in your account before you use them in campaigns.
</Aside>

<Tabs>
<TabItem label="Lead form">

This lead form writes name and email as tags, sends a `promo_requested` event, shows a thank-you message, then closes the in-app.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-13.webp" alt="HTML lead form in the in-app editor with name and email fields and a Send me the code button" width="360"/>

<details>
<summary>HTML code</summary>

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
  body { margin: 0; padding: 20px; font-family: Arial, sans-serif; }
  h2 { font-size: 18px; margin-bottom: 8px; color: #222; }
  p { font-size: 14px; color: #666; margin-bottom: 20px; }
  input {
    width: 100%;
    padding: 12px;
    margin-bottom: 12px;
    border: 1px solid #ddd;
    border-radius: 8px;
    font-size: 15px;
    box-sizing: border-box;
  }
  button {
    width: 100%;
    padding: 14px;
    background: #FF6B35;
    color: white;
    border: none;
    border-radius: 8px;
    font-size: 16px;
    font-weight: bold;
    cursor: pointer;
  }
  .thanks { display: none; text-align: center; padding: 40px 0; font-size: 18px; color: #333; }
</style>
</head>
<body>

<h2>Get your 20% discount</h2>
<p>Leave your name and email. We'll send the promo code right away.</p>

<div id="form">
  <input type="text" id="name" placeholder="Your name" />
  <input type="email" id="email" placeholder="Your email" />
  <button onclick="submit()">Send me the code</button>
</div>

<div class="thanks" id="thanks">
  🎉 Done! Check your inbox for the promo code.
</div>

<script>
function submit() {
  const name = document.getElementById('name').value.trim();
  const email = document.getElementById('email').value.trim();
  if (!name || !email) return;

  pushwoosh.sendTags({ name: name, email: email });
  pushwoosh.postEvent("promo_requested", { email: email });

  document.getElementById('form').style.display = 'none';
  document.getElementById('thanks').style.display = 'block';
  setTimeout(() => pushwoosh.closeInApp(), 3000);
}
</script>

</body>
</html>
```


</details>

</TabItem>
<TabItem label="Survey">

This survey saves the selected workout time as a tag, sends a `schedule_survey_completed` event, shows a thank-you message, then closes the in-app.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-14.webp" alt="HTML survey in the in-app editor asking when the user prefers to work out with four time options" width="360"/>

<details>
<summary>HTML code</summary>

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
  body { margin: 0; padding: 20px; font-family: Arial, sans-serif; text-align: center; }
  h2 { font-size: 18px; margin-bottom: 6px; color: #222; }
  p { font-size: 13px; color: #888; margin-bottom: 20px; }
  .option {
    display: block;
    width: 100%;
    padding: 14px;
    margin-bottom: 10px;
    background: #f5f5f5;
    border: 2px solid transparent;
    border-radius: 10px;
    font-size: 15px;
    cursor: pointer;
    box-sizing: border-box;
  }
  .option:hover { border-color: #FF6B35; background: #fff5f0; }
  .thanks { display: none; font-size: 17px; padding: 40px 0; color: #333; }
</style>
</head>
<body>

<h2>When do you prefer to work out?</h2>
<p>Help us schedule the best classes for you</p>

<button class="option" onclick="pick('morning')">☀️ Morning (6:00–10:00)</button>
<button class="option" onclick="pick('afternoon')">🌤️ Afternoon (12:00–15:00)</button>
<button class="option" onclick="pick('evening')">🌙 Evening (18:00–21:00)</button>
<button class="option" onclick="pick('weekend')">📅 Weekends only</button>

<div class="thanks" id="thanks">Got it! We'll send you the best schedule 💪</div>

<script>
function pick(time) {
  pushwoosh.sendTags({ preferred_time: time });
  pushwoosh.postEvent("schedule_survey_completed", { time: time });
  document.querySelector('h2').style.display = 'none';
  document.querySelector('p').style.display = 'none';
  document.querySelectorAll('.option').forEach(el => el.style.display = 'none');
  document.getElementById('thanks').style.display = 'block';
  setTimeout(() => pushwoosh.closeInApp(), 2000);
}
</script>

</body>
</html>
```


</details>

</TabItem>
<TabItem label="Video">

This example embeds a YouTube video in the in-app message.

<details>
<summary>HTML code</summary>

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>In-App Video Example</title>
<style>
  body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 20px;
    text-align: center;
  }
  .video-container {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: hidden;
  }
  .video-container iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
</style>
</head>
<body>

<h1>In-App Video Example</h1>

<div class="video-container">
       <iframe src="https://www.youtube.com/embed/TN1uyD2mONs?autoplay=1&mute=1" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

</body>
</html>
```


</details>

</TabItem>
</Tabs>



### Menu

The **Menu** block places several clickable items in a row or column. Use it for a navigation bar or a list of company contacts.

For each menu item, set:

* **Label:** the text users see
* **URL:** where the item opens
* **Target:** same tab or a new tab

In the block settings, you can also set:

* **Direction:** Horizontal or Vertical
* **Alignment:** Left, Center, or Right
* **Separator:** an optional divider between items
* Font, size, weight, letter spacing, and link/text colors

### Social

The **Social** block displays a row of social media icons that link to your profiles. Use it to send users to Facebook, Instagram, X, and other platforms from the in-app message.

Add platform entries, then set alignment, icon size, and the gap between icons.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-15.webp" alt="Social block settings with TikTok, Instagram, and Facebook links plus Alignment, Icon size, and Gap" width="320"/>

### Countdown timer

The **Timer** block is a countdown in the in-app message. Use it for limited-time offers, flash sales, and event reminders.

To set it up:

1. In **Countdown**, set **End date** and **End time**, then choose the **Timezone** and **Language** for the timer labels.
2. Turn **Labels** on to show "days / hours / minutes / seconds" captions under the digits, or off for numbers only.
3. In **Appearance**, set **Background**, **Digits color**, **Labels color**, and the font size for digits (default 40px) and labels (default 16px).
4. Adjust **Spacing** (padding) as needed.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-16.webp" alt="Timer block settings with Countdown end date and time, Labels, Appearance, and Spacing options"/>

### Columns

**Columns** split the canvas into side-by-side sections so you can place content next to each other in one row.

Drag one of these blocks onto the canvas:

* **2 columns:** two equal columns
* **3 columns:** three equal columns
* **4 columns:** four equal columns
* **33 / 67:** left column about 33% wide, right about 67%
* **67 / 33:** left column about 67% wide, right about 33%

Then add content to each column. To change spacing for all columns in the template, open **Settings** → **Columns defaults** and adjust outer padding, column padding, and the gap between columns.

### Products

A **Products** block shows a grid of product cards from one shared template. Each card can include an image, title, description, price, and a buy button. The template repeats for every product.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-47.webp" alt="Products block with two product cards showing image, title, description, price, and Shop now button"/>

In the settings panel, under **Source**, choose where the products come from:

* **Manual:** enter products by hand, or click **Pick from catalog…** to select specific items from your [Product Catalog](/product/content/product-catalog/) by ID. You can mix both in the same block.
* **Catalog rule:** pull products automatically by category and sort order, resolved fresh from the catalog when the message is shown.
* **Cart:** show the items from each user's current abandoned cart. [How to set up an abandoned cart campaign](/product/how-to-guides/lifecycle-marketing-campaigns/how-to-set-up-an-abandoned-cart-campaign/)

<Aside type="note">
**Catalog rule** and **Cart** need **Content Templates** on your plan, and an [API access token](/developer/api-reference/api-access-token/) (**Settings → API Access**). If the **Source** selector won't switch to one of them, or the block doesn't render products, contact Support or your account manager, or create a token and re-select the source.
</Aside>

Once you've picked a source, these settings control how the grid and its cards look:

* **Number of products** (or **Max products shown** for **Cart**): how many cards to show.
* **Columns:** 1, 2, or 3 cards per row.
* **Gap:** the space between cards.
* **Description limit:** the character limit description text is trimmed to, so cards stay a consistent size.
* **Card template:** pick a layout, then set **Card background**, **Card corner radius**, and **Content padding** for every card.

## Save and reuse blocks

Save a block to reuse it in this or other in-app templates instead of rebuilding it each time.

1. Select the block on the canvas.
2. Click the bookmark icon (**Save block for reuse**) in the block's toolbar and give it a name.

<img src="/rich-media-create-rich-media-in-the-built-in-editor-42.webp" alt="Card block toolbar with Move up, Move down, Duplicate, Delete, Save block for reuse, and Ask AI icons"/>

Saved blocks appear under **Saved blocks** at the bottom of the **Blocks** tab.

* Drag a saved block onto the canvas, or click it to add it at the end of the template.
* Click the **×** on a saved block's tile to delete it.

### Keep copies in sync

When you save a block, turn on **Keep copies in sync** to link every inserted copy to the same source. Edit the source once, and the change applies everywhere that block is used.

A synced copy is locked on the canvas. You can't edit it directly. Select the copy to open its settings:

* **Edit synced block:** unlock this copy so you can change it. A banner appears at the top. Click **Apply to all** to save your changes to the source and every other copy, or **Cancel** to discard them. You can unlock only one synced block at a time.
* **Update from source:** replace this copy with the latest version from the source.
* **Detach from source:** unlink this copy from the source so you can edit it on its own.

<Aside type="note">
Each time you open an in-app template, Pushwoosh checks its synced copies and updates any that are out of date. A toast shows how many were refreshed. If the source has newer content, the copy's settings show a warning until you reopen the template or click **Update from source**. If the source was deleted, the copy keeps its last content and you can only **Detach from source**.
</Aside>