# How to add customer HTML after "post\_1"

**URL:** https://meta.discourse.org/t/how-to-add-customer-html-after-post-1/123068
**Category:** Support
**Created:** [July 16, 2019, 12:28pm UTC](https://meta.discourse.org/t/how-to-add-customer-html-after-post-1/123068 "2019-07-16T12:28:00Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![DigitalStartup](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/digitalstartup/32/118242_2.png) [@DigitalStartup](https://meta.discourse.org/u/DigitalStartup)
#### Post date: [July 16, 2019, 12:28pm UTC](https://meta.discourse.org/t/how-to-add-customer-html-after-post-1/123068/1 "2019-07-16T12:28:00Z")

</div>

I’d like to add a customer banner (for affiliate purposes) inside of my Posts. **Specifically** , I’d like to add this block of (example) HTML right after `<article id="post_1..."`.

```plaintext
<div id="custom-ad">
    <a href="example.com">
        <img src="https://picsum.photos/id/74/750/90">
    </a>
</div>

```

Therefore, looking something like this:

 ![bannerexample](https://global.discourse-cdn.com/meta/original/3X/2/5/259c1ac4bea96c453cff08f2b5a79362e1367b66.png)

I’ve had limited success with CSS `:after`. And so was wondering if this is something that could be done from inside the `</HEAD>` using a `<script>` like [this example](https://meta.discourse.org/t/extending-the-about-page/110866/5).

**EDIT:** Having played around with it a little more, it seems cleaner to insert the banner at the end of `<div class="topic-map">` instead.:

```plaintext
<div class="topic-map">
    <section class="map map-collapsed">...</section>
    CUSTOM HTML HERE
</div>

```

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [July 16, 2019, 1:58pm UTC](https://meta.discourse.org/t/how-to-add-customer-html-after-post-1/123068/2 "2019-07-16T13:58:48Z")

</div>

Posts are [widgets](https://meta.discourse.org/t/a-tour-of-how-the-widget-virtual-dom-code-in-discourse-works/40347) which means what you’re trying to do will involve a bit more work that just adding html.

Discourse themes have the ability to [decorate widgets](https://meta.discourse.org/t/developer-s-guide-to-discourse-themes/93648#heading--4-c-6) so you can leverage on that.

Decorating a widget is explained in the link above so let’s focus on what you’re trying to do - add markup after the first post in every topic.

Start by adding the markup to all posts. So something like this

```plaintext
<script type="text/discourse-plugin" version="0.8">
api.decorateWidget("post:after", helper => {
  return helper.h("div", "test text");
});
</script>

```

to the header section of your theme. That should be enough to add “test text” below every post.

 ![widget001](https://global.discourse-cdn.com/meta/original/3X/2/7/271f86f6d7ebb76da642ca4bcbc9653dc8810b80.png)

Let’s breakdown the script above

`api.decorateWidget("post:after", helper => {`

calls the decorateWidget method, the target widget being `post` and the target location being `after`. So after a post widget.

`helper` is a built in helper that gives you access to a bunch of stuff that I will explain later

`return helper.h("div", "test text")`

This is the desired additional markup you want to add. You might notice that there’s no html in there and that’s because discourse widgets emit virtual nodes and not raw html.

Explaining what virtual nodes are or how the syntax works is outside of the scope for this topic, so I’ll skip that. I’ve added a note to write a howto for authoring virtual nodes but here are a couple of example for now

`helper.h("div", "test text")`

renders

```plaintext
<div>test text</div>

```

and

```plaintext
return helper.h("div#custom-ad", [
  helper.h(
    "a.custom-ad-link",
    { href: "example.com" },
    helper.h("img", { src: "https://picsum.photos/id/74/750/90" })
  )
]);

```

will render

```plaintext
<div id="custom-ad">
  <a href="example.com" class="custom-ad-link">
    <img src="https://picsum.photos/id/74/750/90">
  </a>
</div>

```

In a nutshell, a node looks like this

```plaintext
helper.h(selector, {properties}, children)

```

I’ll explain this more in the virtual node howto.

So, now you have the nodes ready, you would just need to add the whole script to the header section of your theme, so something like this

```plaintext
<script type="text/discourse-plugin" version="0.8">
  api.decorateWidget("post:after", helper => {
    return helper.h("div#custom-ad", [
      helper.h(
        "a.custom-ad-link",
        { href: "example.com" },
        helper.h("img", { src: "https://picsum.photos/id/74/750/90" })
      )
    ]);
  });
</script>

```

However, there’s still a problem here, the ad will be inserted below every post in the stream, which is not ideal.

 ![widget002](https://global.discourse-cdn.com/meta/original/3X/4/9/49e31312a80b2ebafea7193c86648cc968a789ff.jpeg)

This is where the helper comes in handy, the post attributes are passed to the helper, so you can do a quick

```plaintext
console.log(helper)

```

You’ll be able to see all the post attributes available for you to work with.

 ![widget003](https://global.discourse-cdn.com/meta/original/3X/9/b/9ba7293ea4e0c74c5b67d3f36416fce958bb78e3.png)

those are just examples, there’s more in there.

Luckily, the `firstPost` attribute is available for us here, so all you have left is to feed that into a conditional that will only render the ad markup if it’s indeed the first post, otherwise nothing happens. So something like this:

```plaintext
<script type="text/discourse-plugin" version="0.8">
api.decorateWidget("post:after", helper => {
  const firstPost = helper.attrs.firstPost;
  const h = helper.h;
  if (firstPost) {
    return h("div#custom-ad", [
      h(
        "a.custom-ad-link",
        { href: "example.com" },
        h("img", { src: "https://picsum.photos/id/74/750/90" })
      )
    ]);
  }
});
</script>

```

and that will insert your ad only after the first post. One additional thing to do here is to add a height to the image, otherwise it will cause jitter as it loads. So like I briefly touched on above, the `height` attribute for the image tag is a property, so you’re need to add it next to the `src`

With all of that put together, here’s the final code for what you’re trying to achieve

```plaintext
<script type="text/discourse-plugin" version="0.8">
api.decorateWidget("post:after", helper => {
  const firstPost = helper.attrs.firstPost;
  const h = helper.h;
  if (firstPost) {
    return h("div#custom-ad", [
      h(
        "a.custom-ad-link",
        { href: "example.com" },
        h("img", { src: "https://picsum.photos/id/74/750/90", height: "90" })
      )
    ]);
  }
});
</script>

```

One last note I want to highlight is that you can actually use raw html if virtual nodes prove to be to tricky, but it’s not recommended and it’s much better to use virtual nodes. So the same script with raw html would like like this

```plaintext
<script type="text/discourse-plugin" version="0.8">
  const RawHtml = require("discourse/widgets/raw-html").default;
  api.decorateWidget("post:after", helper => {
    const firstPost = helper.attrs.firstPost;
    if (firstPost) {
      return [
        new RawHtml({
          html: `<div id="custom-ad">
                   <a href="example.com">
                     <img src="https://picsum.photos/id/74/750/90" height="90">
                   </a>
                 </div>`
        })
      ];
    }
  });
</script>

```

but again, this is not recommended.

---

<div class="post-metadata">

### Author: ![DigitalStartup](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/digitalstartup/32/118242_2.png) [@DigitalStartup](https://meta.discourse.org/u/DigitalStartup)
#### Post date: [July 16, 2019, 2:15pm UTC](https://meta.discourse.org/t/how-to-add-customer-html-after-post-1/123068/3 "2019-07-16T14:15:36Z")

</div>

I always appreciate the solutions that explain how to get from A-Z rather than just an answer. Thank you.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [July 16, 2019, 4:04pm UTC](https://meta.discourse.org/t/how-to-add-customer-html-after-post-1/123068/4 "2019-07-16T16:04:19Z")

</div>

I _liked_ this post, but I just want to add: This is a fanatic explanation. I really appreciate posts like this.

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [July 17, 2019, 12:04am UTC](https://meta.discourse.org/t/how-to-add-customer-html-after-post-1/123068/5 "2019-07-17T00:04:51Z")

</div>

That’s because @johani is 🔥 🌶 💪

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [August 16, 2019, 12:04am UTC](https://meta.discourse.org/t/how-to-add-customer-html-after-post-1/123068/6 "2019-08-16T00:04:54Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
