You might have already found yourself in a situation where you would like to distribute parts of layouts among different web applications. Let’s say you manage dozens of websites, and for some reason you need a contact form to send you an email when someone fill it in. You don’t want to implement the HTML forms for all these applications, right?

If you do a quick search on Google, you will find a lot of tutorials explaining how to create iframes, as well as some discussions about inline JavaScript. However, there are important differences between these techniques. This post explains how to create a flexible Widgets API that can be used by both approaches. It also discusses the main difference between these methods, so I hope it helps you to decide when to use each one.

Route, Controller and Views

We can start by creating a route to receive incoming requests for widgets. In the routes.rb add the following line:

In this way, the request /widgets/contact_form for example, would be dispatched to the widgets controller’s show action with { template: 'contact_form' } in the params.

So, let’s create our widgets controller:

The show action can respond_to HTML and JS formats. In both cases, params[:template] should match a view in the app/views/widgets folder. In our example, the expected file is contact_form, but you can create any other piece of view. So, let’s create the contact_form.html.erb file:

Note that send_email_action_url must be replaced by a valid url pointing to the action that deals with this POST. In case you are using url helpers, make sure you use _url instead of _path, as it provides the host, port and path prefix.


One way of rendering our contact form, would be creating an iframe that requests the HTML format. The action show renders the appropriated view using the layout: 'widgets'. Inside the app/views/layouts folder, we must create the widgets.html.erb file.

This layout is minimal, including only the stylesheet file and the view’s content that is rendered by the <%= yield %>. You have to create the widgets.css file inside the apps/assets/stylesheets/ folder, and then define the style for all your widgets.

After the above setup, you can render our contact form in different domains, using the <iframe> tag. Be aware that the iframe will use the style defined in the widgets.css.

PS: Depending on your Rails version, you might have to configure the X-Frame-Options.

  • Browsers are aware that iframes content is served by another domain. So, the same-origin policy applies;
  • Iframes are secure. The same-origin policy prevents scripts to access data from different domains, unless CORS is configured;
  • The content of an iframe is defined by the origin, which includes all the style (css, fonts, js, images, etc.);
  • It is necessary to set the width and height of an iframe. If the iframe’s design is not responsive, you might face difficulties adapting its size in your website.

Inline JavaScript

Another way of rendering our contact form, would be running the JavaScript code provided by the JS format. The js_constructor method wraps the view’s HTML code inside a document.write. Note the layout: false, which means the widgets layout will not be included.

We can render our contact form in different domains using the <script> tag. The script will construct the widget by writing the HTML elements to the DOM. In this way, the widget becomes part of the layout, and the existing style is also applied to it.

  • Browsers execute the script from another domain. The script becomes part of the hosting site, and therefore it does not violate the same-origin policy;
  • Inline JavaScript is not secure, as the script might contain an injection attack. So, you must trust the origin of any script;
  • If the script writes HTML code to the DOM, the hosting site’s stylesheet will define the layout of these added elements.

Deciding When to Use Each Approach

Although we have discussed security issues, our Widgets API does not provide any unsafe script. While the Inline JavaScript should be used to construct the widget as part of the client’s HTML, the Iframe can render the widget as defined in the API server (widgets.css).

Back to our example, we can assume that our contact form has a black background and a white font. So, let’s say we want to include this widget in a clean website with white background and black font.

If your aim is to highlight the contact form in this clean website, you can use the iframe method. However, if you would like to integrate this widget with the website, the Inline JavaScript would be the best choice. So, at the end we can say that both approaches can be used, having situations where each one of them can be more suitable.

Post by: Gabriel Hilal

Originally published at on July 4, 2015.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store