Как написать виджет для сайта

Опыт разработки виджетов для сторонних сайтов

Время на прочтение
6 мин

Количество просмотров 6.1K

Если ваш продукт предоставляет услуги для бизнеса, рано или поздно появится задача создать встраиваемый виджет для сайтов клиентов. Это может быть виджет покупки билетов, прогноза погоды, курса валют, отзывов, комментариев и много чего другого.

В этой статье разберемся, как же сделать качественный виджет, который можно будет  легко поддерживать и расширять.

Библиотека

Не нужно думать, что виджет у вас будет один.

Даже если сейчас это так и других виджетов не предвидится. Или вы уверены, что один виджет может устанавливаться один раз на страницу.

Главная сложность разработки виджетов для сторонних сайтов — сразу верно заложить архитектуру так, чтобы при развитии виджетов не нужно было изменять код, установленный на сайтах. Убедить пользователей виджета заменить код довольно сложно, долго и вызывает волну негатива.

Поэтому сразу проектируем код таким образом, чтобы он позволял вставлять неограниченное число разных виджетов на одну страницу без ограничений. Первое, что приходит в голову: «а давайте просто выведем iframe с нашего сайта?». И сделаем код вида:

<iframe src="https://company.name/my-widget" frameborder="0" scrolling="no" width="300" height="200">
       Ваш браузер не поддерживает фреймы!
</iframe>

И это будет большой ошибкой по нескольким причинам.

Невозможность расширения

У iframe довольно много ограничений, связанных с защитой конфиденциальности в браузере. Даже просто растянуть iframe под размер его содержимого без внешнего javascript кода не получится. Стилизовать можно будет только то, что лежит непосредственно в iframe, на сам тэг и его обертку никак нельзя будет повлиять. 

Может, для начала это не критично, но по мере развития в это легко можно упереться, а код на сайтах уже установлен.

Про то, какие проблемы есть в работе с iframe и их решении, поговорим попозже.

Лишние запросы на бэкенд

Если на сайт будет установлено 5 таких одинаковых виджетов, то на ваш сервер придет 5 одинаковых запросов, хотя по факту нужен был только один. Конечно, можно сделать кеш на nginx и не пропускать запрос дальше, но зачем нам самим себе делать паразитные запросы? С таким кодом изменить логику получения данных не получится без изменения кода вставки виджета. Если виджет будет установлен на десятках сайтов, даже не самых популярных, в сумме они могут давать заметную нагрузку.

А как надо делать?

Если вы когда-нибудь устанавливали на сайт какой-нибудь виджет, например, от ВК, то могли заметить, что код виджета разделен на две части: библиотеку (SDK) и инициализацию виджетов:

В целом, хорошая практика — посмотреть, как делают другие, так можно сразу перескочить через множество граблей. В этом коде все хорошо, кроме того, что он не асинхронный. Это их право — давать вставлять по умолчанию код, который может заблокировать загрузку страницы, но мы так делать не будем, попозже поговорим об этом. Нам в этом коде важна идея.

Мы видим, что для вставки любого виджета нужно один раз подключить SDK и добавить один пустой тэг с инициализацией виджета. А дальше все делает javascript: он может делать любые запросы и любое их количество на бэкенд, и разработчики виджета могут в любой момент эту логику изменить без изменения кода виджета на сайте. В итоге из html на сайте для виджета должен быть только пустой контейнер с уникальным id. Чтобы не томить вас ожиданием, давайте сразу напишем пример SDK и рендер простого виджета. 

А потом поговорим о том, что же у нас получилось и на что стоит обратить внимание.

Код библиотеки

namespace MyCompany {
    /**
     * Виджет кнопки
     */
    class Button {
        /**
         * Внутренний id кнопки
         */
        protected id: number;

        /**
         * DOM элемент контейнера
         */
        protected containerElement: HTMLElement;

        /**
         * Инстанс api
         */
        protected apiInstance: Api;

        /**
         * Constructor
         * @param {Api} instance
         * @param {string} containerId
         */
        public constructor(instance: Api, containerId: string) {
            this.apiInstance = instance;
            this.containerElement = document.getElementById(containerId);
        }

        /**
         * Инициализация
         */
        public init(): void {
            this.containerElement.innerHTML = '<button>Виджет кнопки</button>';
        }
    }

    /**
     * Основной класс Api
     */
    export class Api {

        /**
         * Виджет кнопки
         * @param {string} containerId
         * @return {MyCompany.Button}
         */
        public button(containerId: string): Button {
            const widget = new Button(this, containerId);
            widget.init();
            return widget;
        }

        /**
         * Запуск колбеков инициализации
         */
        public runInitCallbacks(): void
        {
            let myCompanyApiInitCallbacks = (window as any).myCompanyApiInitCallbacks;
            if (myCompanyApiInitCallbacks && myCompanyApiInitCallbacks.length) {
                setTimeout(function () {
                    let callback;
                    while (callback = myCompanyApiInitCallbacks.shift()) {
                        try {
                            callback();
                        } catch (e) {
                            console.error(e);
                        }
                    }
                }, 0);
            }
        }
    }
}

/**
 * Инициализация Api
 */
if (typeof (window as any)['myCompanyApi'] === 'undefined') {
    (window as any).myCompanyApi = new MyCompany.Api();
    (window as any).myCompanyApi.runInitCallbacks();
}

Код вставки

<!-- в head один раз -->
<script async type="text/javascript" src="https://mycompany.site/js/api/api.min.js"></script>

<!-- в место вызова виджета -->
<div id="button-container-5ef9b197c865f"></div>
<script type="text/javascript">
    (function() {
        var init = function() {
            myCompanyApi.button('button-container-5ef9b197c865f');
        };
        if (typeof myCompanyApi !== 'undefined') {
            init();
        } else {
            (myCompanyApiInitCallbacks = window.myCompanyApiInitCallbacks || []).push(init);
        }
    })();
</script>

Выглядит страшно и как-то избыточно, давайте разбираться, зачем все это.

Асинхронность

Сразу в глаза бросается атрибут async у тэга script. Он позволит браузеру не ждать загрузки нашего скрипта и продолжить отрисовывать сайт. Это важно: если по каким-то причинам наш скрипт будет недоступен (недоступен сервер, фаервол компании), это не должно влиять на скорость загрузки сайта клиента. Но все не так просто. Раз скрипт загружается асинхронно, это значит, что когда браузер дойдет до места, где инициализируется наш виджет, наш SDK может быть еще не загружен, и если просто вызвать метод из библиотеки — будет ошибка, причем плавающая, в зависимости от того, успел загрузиться скрипт или нет.

Поэтому в месте вызова виджета мы должны обработать оба сценария, когда SDK загрузилось и еще нет.

В первом случае мы просто вызываем функцию init(). Во втором — откладываем выполнение этой функции до момента, когда скрипт загрузится, добавляя замыкание в очередь. А последней строчкой в нашем SDK вызывается метод runInitCallbacks, который как раз и выполнит все отложенные инициализации.

Тут же есть защита от повторного подключения SDK, ведь пользователи могут проигнорировать ваши требования и вставить скрипт библиотеки десять раз.

Теперь наш код запускается всегда и не блокирует отрисовку страницы!

Изоляция

Название объекта SDK и id контейнеров должны быть уникальными, ведь наш код будет выполняться на совершенно разных сайтах. Ни в коем случае нельзя нарваться на совпадения. ID контейнеров желательно генерировать уникальными, например, через uniqid(). Нельзя надеяться и на сторонние библиотеки, установленные на сайте, и совсем не желательно приносить их с собой. Да, я о jQuery, как вы уже догадались.

Код виджетов должен быть легковесным и универсальным, сейчас уже не сложно писать кроссбраузерный код нативно. Кроме того, я настоятельно рекомендую использовать TypeScript, но это есть множество причин.

На кодировку сайта тоже не стоит полагаться, и даже в наше время встречаются сайты на cp1251. Поэтому кодировку скрипта нужно явно задать в ответе сервера в заголовке Content-Type.

Код, написанный нами выше, позволяет не останавливаться на одном виджете: сейчас у нас есть только myCompanyApi.button(), но ничего не мешает добавить другие виджеты.

Кеширование

Мы будем постоянно дорабатывать наш SDK, но браузеры кэшируют скрипты, если разработчик не дал других инструкций. Мы должны сами задать время, на которое можно кешировать нашу библиотеку, через заголовок Expires, например, час — адекватное время. С кешированием на фронтенде разобрались, теперь поговорим про бэкенд. Как уже обсуждали выше, обслуживание запросов со сторонних виджетов может создавать ощутимую нагрузку просто от количества сайтов, где виджеты установлены. Но чаще всего данные для всех пользователей в этих виджетах одинаковые, нет смысла запускать приложение, а тем более ходить в базу данных за ними на каждый запрос. Такие запросы вообще дальше nginx можно не пропускать, настроив кеширование на нем. 

Если для отрисовки виджета нужны данные с бэкенда, но в целом можно отрисовать минимальную версию и без него (например, кнопку покупки билетов, но без признака наличия), хорошим тоном будет сделать fallback: если данные не загрузились за полсекунды, рисовать обрезанную версию виджета, а как только данные получены — дорисовывать. Это визуально ускорит загрузку и покажет виджет даже без работающего бэкенда (вдруг он при взаимодействии уже поднимется?).

Немного про iframe

Iframe — по сути, отображение сайта в сайте. Вернемся к нашему кейсу с кнопкой покупки билетов. Если мы хотим при клике открывать попап со страницей выбора места — без iframe нам не обойтись. Какие же там есть нюансы?

Неработающие cookie

Уже давно многие браузеры по умолчанию начинают запрещать использование cookie для сторонних сайтов (это когда домен iframe отличается от родительского сайта). Это значит, что при переходе между страницами внутри фрейма не получится отследить сессию (localStorage тоже не работает).Тут выход простой — не перезагружать страницы и делать SPA. Идентификатор сессии можно будет легко сохранить в переменной в js.

Общение с  SDK

Часто требуется организовать общение нашего SDK с приложением внутри iframe, например, мы хотим при открытии виджета растянуть размер фрейма под размер контента. Для этого нам нужно сообщить размер контента из iframe в родительское окно. Это можно легко сделать через postMessage. Будьте внимательны при передаче конфиденциальных данных и верно указывайте targetOrigin, иначе данные могут «подслушать» другие сайты.

Спасибо за внимание, надеюсь, вы узнали для себя что-то новое.

Сергей Никитченко, Студия Валерия Комягина


май
21
, 2016

Встраиваемые виджетыКаждый раз подключая на своих сайтах готовое решение от сервисов вроде disqus или google-аналитики, я удивляюсь простоте интеграции достаточно сложного функционала. Поставил в код 3 строчки javascript-кода — и у тебя уже развернулся блок с комментариями. Еще 2 строчки — и доступна аналитика от гугла или яндекса. Конечно, никакого волшебства при этом не происходит, те самые 3 строчки кода подтягивают с удаленного сервера весь нужный код, и по сути разворачивают небольшое веб-приложение на страницах Вашего сайта. Но как это устроено внутри и как это сделать самому? Разобраться с этим было достаточно интересно, и в итоге у меня получился небольшой виджет, который работает именно по такой простой схеме встраивания и при этом еще выполняют некоторые полезные вещи. Далее подробности.

Зачем нужны виджеты?

Здесь все просто: допустим, у нас есть какой-то неимоверно крутой сервис.
Он настолько крут, что мы хотим поделиться нашими возможностями со всем миром (а может, и продать их).
Но здесь всплывают несколько моментов.
Во-первых, мы не готовы предоставлять открыто наши исходники.
Во-вторых, нужна максимально простая схема встраивания нашего функционала в сторонние сайты.
В-третьих, мы хотим, чтобы наши пользователи были уверены,
что использование нашего сервиса ничем не навредит их сайту.

Для этой цели хорошо подходят iframe-ы.
Это фактически отдельные html-страницы, которые встраиваются в другие страницы, при этом не имея доступа к своему «родителю».
То есть в iframe можно встроить наше веб-приложение,
которое будет спокойно выполнять свою работу, не вмешиваясь в основной сайт.
А что именно будет делать Ваш виджет, строить систему комментариев на странице,
показывать прикольную игрушку или рисовать интерактивный рекламный баннер —
дело исключительно Вашего вкуса и фантазии.

В этой статье на игрушку мы замахиваться не будем, а рассмотрим, как создать встраиваемый виджет для определения погоды.
Конечно, для этого есть много различных погодных сервисов, но нам неинтересно воспользоваться готовым решением.
Хочется создать простенький виджет своими руками, чтобы понять,
как это вообще работает и в дальнейшем применить знания уже для каких-то полезных вещей.
Заодно попутно освежим знания в нативном javascript и php.

Что будем делать?

Мы создадим виджет, который рисует форму с прогнозом погоды на завтра.
В качестве примера возьмем только температуру, но как увидите дальше, легко можно будет добавить и другие данные.
В виджете будет располагаться информация о температуре на завтра,
раскрывающийся список с возможностью выбрать город.
Кнопка Обновить будет отправлять запрос на сервер, который в свою очередь обращается на сторонний сервис для определения погоды
и возвращает нам нужную инфу. Эти данные мы обрабатываем и возвращаем в браузер клиенту.
Где уже клиентская часть виджета перехватывает информацию и выводит ее пользователю.

Выглядит это проще, чем звучит — можете сразу посмотреть, что в итоге получится —
Демо страницы с виджетом

Здесь мы видим какую-то страницу, где рассказывается, что якобы мы умеем определять погоду.
И демонстрируем нашим посетителям формочку, дабы они могли убедиться, что погоду действительно можно узнать прямо здесь.

Я не развлекался с версткой формы, цель статьи не в этом.
В реальном мире мы, конечно же, создали бы симпатичную формочку, которая привлекала бы внимание.

Итак, вернемся. Люди узнают погоду, возможно, даже не задумываясь о том, что фактически пользуются другим сервисом.
Но все довольны и счастливы, Вы получаете посетителей на свой сайт, клиенты — нужную информацию.

Здесь нужно небольшое уточнение: смысл виджетов в том, чтобы предоставлять уникальный, удобный, интересный функционал.
Мы не даем в нашем примере какую-то особенную информацию.
Погоду можно узнать где угодно.
Но в познавательных целях, так как мы сами пока ничего не умеем делать, возьмем данные по погоде с сервиса
Прогноз погоды в России и СНГ.
Они любезно предоставляют бесплатный api, коим мы и воспользуемся.

По технологиям

Тоже ничего сложного. Про iframe я уже проговорился.
javascript-код будем писать на vanillaJS, без единой дополнительной библиотеки.
Даже без jQuery для манипуляции DOM.
Наша цель еще состоит и в том, чтобы полученный виджет был максимально легковесным,
и ни к чему тащить в браузер пользователя мешок дополнительных библиотек для облегчения своей работы.
Поэтому вспомним, как работать с DOM и отправлять ajax-запросы на нативном javascript, и наши клиенты скажут нам спасибо.
Серверная часть — пара десятков строк кода на php.

Пишем код. Создаем базовую страницу

Страницу, на которой будет располагаться наш будущий виджет.
Напишем там пару строчек текста о том, какие мы классные в плане умения прогнозировать погоду на завтра.
Это будет файл index.html — обычная html-страничка.
В секции head напишем так:

    Webdevkin. Демонстрация виджета Погода
	
	

В секции body вот так:

	

Погода в городах России

Здесь мы расскажем Вам про погоду в разных замечательных городах нашей страны!

Подписывайтесь на наши обновления и Вы всегда будете узнавать погоду вовремя!

Что здесь из интересного? В файле css/style.css будем хранить стили для страницы (не для виджета!).
И в нужном месте создаем iframe.
В атрибуте src iframe-a ставим ссылку на виджет, в нашем случае — https://webdevkin.ru/examples/weather/widget/widget.html.
Мы убираем у него границу и возможность скроллинга и задаем руками размеры виджета.
Конечно, интереснее создать адаптивный, но до этого доберемся позже.

Стили для страницы, без особых изысков:

    body {
    	font-family: Arial;
    	font-size: 14px;
    }
    
    .wrapper {
    	width: 960px;
    	margin: 0 auto;
    }
    
    .weather-widget-container {
        margin: 30px 0;
    }

Заготовка для виджета

Виджет представляет из себя обычный html-документ.
В чем отличие? Первое — мы не будем заморачиваться с лишними мета-тегами, потому как поисковикам наш виджет не нужен.
И второе — и стили, и js-код мы напишем прямо в коде html-страницы. Нам это нужно, чтобы сделать загрузку виджета максимально быстрой,
а уменьшение числа запросов к веб-серверу в этом нам поможет.
Все, что нужно, мы загрузим одним файлом.

В секции head у нас будет такой код:

    
    

В секции body:

    
        
        
    

Рассмотрим эти блоки подробнее.

Разметка для виджета

    

Здесь обычная форма.
Сверху небольшая панель, где мы будем выводить температуру.
Дальше select с выбором города.
Значения value у городов взяты с сервиса meteoservice.ru, где именно, расскажу позже,
в разделе, где будем непосредственно получать данные о погоде.
И в конце кнопка Обновить.
Верстка у нас будет на классах, айдишники проставлены тем элементам, доступ к которым нужен из кода javascript.
Префикс wbd- (от webdevkin) используется для удобства, чтобы не путать разметки виджета и основной страницы.

Стили для виджета

    html, body, body * {
        margin: 0;
        padding: 0;
    }

    .wbd-widget, .wbd-widget * {
        box-sizing: border-box;
        font-family: Ubuntu;
    }

    .wbd-widget {
        border: solid 1px #333;
        padding: 20px;
        color: black;
    }

    .wbd-widget__info {
        color: steelblue;
        font-size: 16px;
        text-align: center;
    }

    .wbd-widget__form-label {
        display: block;
        line-height: 30px;
    }

Стили для виджета максимально просты — Вы можете написать их под себя, как угодно.
Не забываем, что стили ставим прямо в html-файл виджета в раздел head — style.

javascript-код виджета.

Напишем класс, в котором будут методы инициализации, привязки событий и получения данных с сервера.
Не забываем, что код будем писать на нативном js, так как не хотим обременять пользователей лишним грузом библиотек.

    var WeatherWidget = (function() {
        
        // Для выполнения ajax-запросов
        var XHR = ("onload" in new XMLHttpRequest()) ? XMLHttpRequest : XDomainRequest;

        // Конструктор виджета
        function Widget() {
            this.url = 'https://webdevkin.ru/examples/weather/widget/widget.php';
            this.ui = {
                updateBtn: null,
                citySelect: null,
                temperatureSpan: null
            };

            this.init();
        }

        // Обновление данных о погоде
        Widget.prototype._updateData = function(e) {
            // Отправка ajax-запроса на сервер
        }

        // Инициализация компонентов ui
        Widget.prototype._initUI = function() {
            this.ui.updateBtn = document.getElementById('wbd-widget-update');
            this.ui.citySelect = document.getElementById('wbd-widget-city');
            this.ui.temperatureSpan = document.getElementById('wbd-widget-temperature');
        }

        // Привязывание событий
        Widget.prototype._bindHandlers = function() {
            this.ui.updateBtn.addEventListener('click', Widget.prototype._updateData.bind(this));
        }

        // Инициализация виджета
        Widget.prototype.init = function() {
            this._initUI();
            this._bindHandlers();
            this._updateData();
        }

        // Возвращаем класс виджета
        return Widget;
    })();

    new WeatherWidget();

Что здесь происходит?
Мы создаем модуль на основе замыкания WeatherWidget, внутри оного пишем класс Widget,
в прототип которого закидываем нужные методы и возвращаем его из замыкания.
Последней строкой мы создаем экземпляр виджета — new WeatherWidget();

Переменная XHR нужна для выполнения ajax-запросов.
В конструкторе инициализируем свойство url, по которому будем получать данные о погоде.
Также есть объект ui, в котором хранятся 3 поля — те самые элементы DOM, к которым нам нужен доступ из js-кода.
Инициализируются они позже, в методе _initUI().
Метод init() вызывает инициализацию ui, привязку событий и обновление данных с сервера
(мы же хотим, чтобы при отрисовке виджета пользователь сразу видел погоду без нажатия на Обновить).
В _bindHandlers привязывается метод _updateData к клику на кнопку Обновить.
Это единственная «интерактивная» часть нашего виджета.

Обратите внимание на конструкцию Widget.prototype._updateData.bind(this).
Здесь явным образом привязываем контекст — нам нужно, чтобы в методе _updateData
this всегда указывал на экземпляр класса Widget.
Сейчас будет видно, зачем — рассмотрим код метода _updateData

Получение данных с сервера, метод _updateData

    // Обновление данных о погоде
    Widget.prototype._updateData = function(e) {
        e && e.preventDefault();

        var xhr = new XHR(),
            city = this.ui.citySelect.value,
            temperatureSpan = this.ui.temperatureSpan,
            data = 'city=' + city,
            resp;

        xhr.open('POST', this.url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(data);

        xhr.onreadystatechange = function() {
            if (this.readyState != 4) return;
            if (this.status != 200) {
                console.log('Request error');
                return;
            }
            resp = JSON.parse(this.responseText);
            temperatureSpan.innerHTML = resp.temperature;
        }
    }

Обращаю внимание, что в параметры метода передаем свойство e (event).
Оно нужно, чтобы сделать preventDefault в самом начале, дабы не перезагрузить наш виджет
(иначе сработает submit формы).

Но делаем мы это такой строчкой

e && e.preventDefault();

Эта дополнительная проверка на наличие параметра e нужна, потому что когда мы вызываем this._updateData(),
параметр e будет равен undefined, и соответственно e.preventDefault() выкинет исключение.

После этого мы создаем нужные переменные, объект для ajax-запроса, выбранный город и DOM-элемент,
в который выводим значение температуры, полученной с сервера.
data будет отправляться в ajax-запросе, resp — это ответ от сервера.
Дальше мы открываем соединение и отправляем данные на сервер.
Дожидаемся ответа 200 от сервера и выводим полученную температуру в span.
Условимся, что от сервера приходит json-строка в формате {«code»: «success», «temperature»: «диапазон температур»}.
Традиционно обработку ошибок оставлю на Вашу совесть, все делают по-разному.
И наконец, нам осталось узнать, как получить данные о погоде с нашего сервера.

Как узнавать погоду?

Как я уже упоминал, мы воспользуемся сайтом meteoservice.ru.
Он предоставляет возможность получить xml-файл с данными о погоде по любому гододу СНГ.
Например, по этой ссылке
доступна погода по Москве.
С нашего сервера мы будем запрашивать этот файлик curl-ом, парсить его на нашей стороне, извлекать данные о температуре
и возвращать ее обратно в браузер.
Каждому городу нужно заранее поставить в соответствие нужный код (37 — Москва), узнать их можно
здесь.
Как работать с curl, можно узнать в этой статье на webdevkin-е

Рекомендую пользоваться этим сервисом с осторожностью.
Когда статья уже почти была готова, неожиданно поменялся формат ответа по запросу о погоде.
Отрубился вывод прогноза по времени суток, который я изначально хотел продемонстрировать в виджете.
Пришлось частично переписывать код и уменьшать функциональность виджета, что меня не порадовало.
Не знаю, как часто происходят у них такие вещи, но пользоваться сервисом в реальном приложении не советую.

Пишем php-код для получения информации о погоде

Как брать данные, уже понятно, алгоритм прост: вытаскиваем из $_POST параметр city — выбранный город,
формируем строку вида http://xml.meteoservice.ru/export/gismeteo/point/$cityId.xml.
Это путь к файлу с погодой. Отправляем на него get-запрос curl-ом.
Полученный ответ парсим и вытаскиваем из него нужные параметры: минимальная и максимальная температуры.
Полученные числа отдаем в json-объекте обратно в браузер.

    $cityId = (int)$_POST['city'];
    
    $url = "http://xml.meteoservice.ru/export/gismeteo/point/$cityId.xml";
    
    $temperature = '';
    if ($curl = curl_init()) {
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        $result = curl_exec($curl);
        curl_close($curl);
        
        $xml = simplexml_load_string($result);
        $object = $xml->REPORT->TOWN->FORECAST[0]->TEMPERATURE;
        $temperature = $object['min'] . '-' . $object['max'];
    }
    
    echo json_encode(array(
        'code' => 'success',
        'temperature' => $temperature
    ));

Поясню про simplexml_load_string — эта функция создает xml-объект, который мы уже можем парсить.
А создается объект из строки xml, которую мы получаем от сервиса погоды.

REPORT->TOWN->FORECAST[0]->TEMPERATURE — это путь по узлам xml, чтобы добраться до нужных значений температуры.
Пройдите по ссылке выше (московская погода) и наглядно увидите эти пути.

Если что-то непонятно, спрашивайте в комментариях.

Итого

И на этом все! Мы создали несложный виджет для получения информации о погоде.
Главная его особенность в том, что его очень легко встроить на любой сайт, достаточно всего лишь
вставить в html-код такие строки

	
	
	

Еще раз ссылки:

Демо страницы с виджетом

Архив с исходниками

Полагаю, что есть масса вариантов применения таких виджетов, от сбора различной информации до рекламных баннеров.
А у Вас есть идеи, где это можно применить? Поделитесь в комментариях!

Что еще почитать на похожую тему

Анонсы статей, обсуждения интернет-магазинов, vue, фронтенда, php, гита.

Истории из жизни айти и обсуждение кода.

Если ваш продукт предоставляет услуги для бизнеса, рано или поздно появится задача создать встраиваемый виджет для сайтов клиентов. Это может быть виджет покупки билетов, прогноза погоды, курса валют, отзывов, комментариев и так далее.

«Виджет» — это универсальная «надстройка», которую можно установить на любой сайт с минимальными усилиями. Мы создали виджет электронной коммерции для «Профтикет», одной из ведущих систем на билетном рынке. Сейчас наш виджет успешно используют в МХТ имени Чехова, Современнике, Сатириконе, Цирке Никулина, Театриуме Терезы Дуровой и на других известных площадках.

В этой статье разберемся, как же сделать качественный виджет, который можно будет легко поддерживать и расширять.

Библиотека

Не нужно думать, что виджет у вас будет один.

Даже если сейчас это так и других виджетов не предвидится. Или вы уверены, что один виджет может устанавливаться один раз на страницу.

Главная сложность разработки виджетов для сторонних сайтов — сразу верно заложить архитектуру так, чтобы при развитии виджетов не нужно было изменять код, установленный на сайтах. Убедить пользователей виджета заменить код довольно сложно, долго и вызывает волну негатива.

Поэтому сразу проектируем код таким образом, чтобы он позволял вставлять неограниченное число разных виджетов на одну страницу без ограничений. Первое, что приходит в голову: «а давайте просто выведем iframe с нашего сайта?».

И сделаем код iframe вида:

<iframe src=»https://company.name/my-widget» frameborder=»0″ scrolling=»no» width=»300″ height=»200″>
Ваш браузер не поддерживает фреймы!
</iframe>

И это будет большой ошибкой по нескольким причинам.

Невозможность расширения

У iframe довольно много ограничений, связанных с защитой конфиденциальности в браузере. Даже просто растянуть iframe под размер его содержимого без внешнего javascript кода не получится. Стилизовать можно будет только то, что лежит непосредственно в iframe, на сам тэг и его обертку никак нельзя будет повлиять.

Может, для начала это не критично, но по мере развития в это легко можно упереться, а код на сайтах уже установлен.

Про то, какие проблемы есть в работе с iframe и их решении, поговорим попозже.

Лишние запросы на бэкенд

Если на сайт будет установлено 5 таких одинаковых виджетов, то на ваш сервер придет 5 одинаковых запросов, хотя по факту нужен был только один. Конечно, можно сделать кеш на nginx и не пропускать запрос дальше, но зачем нам самим себе делать паразитные запросы? С таким кодом изменить логику получения данных не получится без изменения кода вставки виджета. Если виджет будет установлен на десятках сайтов, даже не самых популярных, в сумме они могут давать заметную нагрузку.

А как надо делать?

Если вы когда-нибудь устанавливали на сайт какой-нибудь виджет, например, от ВК, то могли заметить, что код виджета разделен на две части: библиотеку (SDK — Software Development Kit) и инициализацию виджетов:

В целом, хорошая практика — посмотреть, как делают другие, так можно сразу перескочить через множество граблей. В этом коде все хорошо, кроме того, что он не асинхронный. Это их право — давать вставлять по умолчанию код, который может заблокировать загрузку страницы, но мы так делать не будем, попозже поговорим об этом. Нам в этом коде важна идея.

Мы видим, что для вставки любого виджета нужно один раз подключить SDK и добавить один пустой тэг с инициализацией виджета. А дальше все делает javascript: он может делать любые запросы и любое их количество на бэкенд, и разработчики виджета могут в любой момент эту логику изменить без изменения кода виджета на сайте. В итоге из html на сайте для виджета должен быть только пустой контейнер с уникальным id. Чтобы не томить вас ожиданием, давайте сразу напишем пример SDK и рендер простого виджета.

А потом поговорим о том, что же у нас получилось и на что стоит обратить внимание.

Код библиотеки:

namespace MyCompany {
/**
* Виджет кнопки
*/
class Button {
/**
* Внутренний id кнопки
*/
protected id: number;

/**
* DOM элемент контейнера
*/
protected containerElement: HTMLElement;

/**
* Инстанс api
*/
protected apiInstance: Api;

/**
* Constructor
* @param {Api} instance
* @param {string} containerId
*/
public constructor(instance: Api, containerId: string) {
this.apiInstance = instance;
this.containerElement = document.getElementById(containerId);
}

/**
* Инициализация
*/
public init(): void {
this.containerElement.innerHTML = ‘Виджет кнопки’;
}
}

/**
* Основной класс Api
*/
export class Api {

/**
* Виджет кнопки
* @param {string} containerId
* @return {MyCompany.Button}
*/
public button(containerId: string): Button {
const widget = new Button(this, containerId);
widget.init();
return widget;
}

/**
* Запуск колбеков инициализации
*/
public runInitCallbacks(): void
{
let myCompanyApiInitCallbacks = (window as any).myCompanyApiInitCallbacks;
if (myCompanyApiInitCallbacks && myCompanyApiInitCallbacks.length) {
setTimeout(function () {
let callback;
while (callback = myCompanyApiInitCallbacks.shift()) {
try {
callback();
} catch (e) {
console.error(e);
}
}
}, 0);
}
}
}
}

/**
* Инициализация Api
*/
if (typeof (window as any)[‘myCompanyApi’] === ‘undefined’) {
(window as any).myCompanyApi = new MyCompany.Api();
(window as any).myCompanyApi.runInitCallbacks();
}

Код вставки:

<!— в head один раз —>
<script async type=»text/javascript» src=»https://mycompany.site/js/api/api.min.js»></script>

<!— в место вызова виджета —>
<div id=»button-container-5ef9b197c865f»></div>
<script type=»text/javascript»>
(function() {
var init = function() {
myCompanyApi.button(‘button-container-5ef9b197c865f’);
};
if (typeof myCompanyApi !== ‘undefined’) {
init();
} else {
(myCompanyApiInitCallbacks = window.myCompanyApiInitCallbacks || []).push(init);
}
})();
</script>

Выглядит страшно и как-то избыточно, давайте разбираться, зачем все это.

Асинхронность

Сразу в глаза бросается атрибут async у тэга script. Он позволит браузеру не ждать загрузки нашего скрипта и продолжить отрисовывать сайт. Это важно: если по каким-то причинам наш скрипт будет недоступен (недоступен сервер, фаервол компании), это не должно влиять на скорость загрузки сайта клиента. Но все не так просто. Раз скрипт загружается асинхронно, это значит, что когда браузер дойдет до места, где инициализируется наш виджет, наш SDK может быть еще не загружен, и если просто вызвать метод из библиотеки — будет ошибка, причем плавающая, в зависимости от того, успел загрузиться скрипт или нет.

Поэтому в месте вызова виджета мы должны обработать оба сценария, когда SDK загрузился и еще нет.

В первом случае мы просто вызываем функцию init(). Во втором — откладываем выполнение этой функции до момента, когда скрипт загрузится, добавляя замыкание в очередь. А последней строчкой в нашем SDK вызывается метод runInitCallbacks, который как раз и выполнит все отложенные инициализации.

Тут же есть защита от повторного подключения SDK, ведь пользователи могут проигнорировать ваши требования и вставить скрипт библиотеки десять раз.

Теперь наш код запускается всегда и не блокирует отрисовку страницы!

Изоляция

Название объекта SDK и id контейнеров должны быть уникальными, ведь наш код будет выполняться на совершенно разных сайтах. Ни в коем случае нельзя нарваться на совпадения. ID контейнеров желательно генерировать уникальными, например, через uniqid(). Нельзя надеяться и на сторонние библиотеки, установленные на сайте, и совсем не желательно приносить их с собой. Да, я о jQuery, как вы уже догадались.

Код виджетов должен быть легковесным и универсальным, сейчас уже не сложно писать кроссбраузерный код нативно. Кроме того, я настоятельно рекомендую использовать TypeScript, на это есть множество причин.

На кодировку сайта тоже не стоит полагаться, и даже в наше время встречаются сайты на cp1251. Поэтому кодировку скрипта нужно явно задать в ответе сервера в заголовке Content-Type.

Код, написанный нами выше, позволяет не останавливаться на одном виджете: сейчас у нас есть только myCompanyApi.button(), но ничего не мешает добавить другие виджеты.

Кеширование

Мы будем постоянно дорабатывать наш SDK, но браузеры кэшируют скрипты, если разработчик не дал других инструкций. Мы должны сами задать время, на которое можно кешировать нашу библиотеку, через заголовок Expires, например, час — адекватное время. С кешированием на фронтенде разобрались, теперь поговорим про бэкенд. Как уже обсуждали выше, обслуживание запросов со сторонних виджетов может создавать ощутимую нагрузку просто от количества сайтов, где виджеты установлены. Но чаще всего данные для всех пользователей в этих виджетах одинаковые, нет смысла запускать приложение, а тем более ходить в базу данных за ними на каждый запрос. Такие запросы вообще дальше nginx можно не пропускать, настроив кеширование на нем.

Если для отрисовки виджета нужны данные с бэкенда, но в целом можно отрисовать минимальную версию и без него (например, кнопку покупки билетов, но без признака наличия), хорошим тоном будет сделать fallback: если данные не загрузились за полсекунды, рисовать обрезанную версию виджета, а как только данные получены — дорисовывать. Это визуально ускорит загрузку и покажет виджет даже без работающего бэкенда (вдруг он при взаимодействии уже поднимется?).

Немного про iframe

Iframe — по сути, отображение сайта в сайте. Вернемся к нашему кейсу с кнопкой покупки билетов. Если мы хотим при клике открывать попап со страницей выбора места — без iframe нам не обойтись. Какие же там есть нюансы?

Неработающие cookie

Уже давно многие браузеры по умолчанию начинают запрещать использование cookie для сторонних сайтов (это когда домен iframe отличается от родительского сайта). Это значит, что при переходе между страницами внутри фрейма не получится отследить сессию (localStorage тоже не работает).Тут выход простой — не перезагружать страницы и делать SPA. Идентификатор сессии можно будет легко сохранить в переменной в js.

Общение с SDK

Часто требуется организовать общение нашего SDK с приложением внутри iframe, например, мы хотим при открытии виджета растянуть размер фрейма под размер контента. Для этого нам нужно сообщить размер контента из iframe в родительское окно. Это можно легко сделать через postMessage. Будьте внимательны при передаче конфиденциальных данных и верно указывайте targetOrigin, иначе данные могут «подслушать» другие сайты.

Спасибо за внимание, надеюсь, вы узнали для себя что-то новое.

Автор статьи: Сергей Никитченко, технический директор, Студия Валерия Комягина.

В этой статье я расскажу как создать с нуля виджет для сайта (на примере виджета опросов). Т.к. основной темой статьи все-таки является создание виджета, то создание самого опроса будет рассмотрено поверхностно.

Пошаговое создание виджета для сайта

Шаг 1. Создание таблиц в БД

В качестве базы данных будем использовать MySQL.
Создадим несколько таблиц:

polls — таблица с опросами

CREATE TABLE `polls`
(
`poll_id` INT(11) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
`question` TEXT
) ENGINE = MYISAM AUTO_INCREMENT = 1 DEFAULT CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI;

answers — таблица с ответами для опросов

CREATE TABLE `answers`
(
`answer_id` INT(11) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
`answer` TEXT,
`num` INT(11) NOT NULL DEFAULT '0',	// порядковый номер ответа
`poll_id_fk` INT NOT NULL DEFAULT '0',
FOREIGN KEY (`poll_id_fk`) REFERENCES polls(`poll_id`)
) ENGINE = MYISAM AUTO_INCREMENT = 1 DEFAULT CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI;

Шаг 2. Создание страницы с опросом

Будем отталкиваться от предпосылки, что наш виджет должен быть произвольной ширины (в рамках разумного), чтобы его можно было встраивать в любые сайты, например, в центре текста по ширине статьи или в боковую часть сайта (обычно узкую). Поэтому при создании страницы с опросом старайтесь проектировать «резиновый» дизайн.

В данном примере ограничимся самым простым выводом опроса.

<?php
	// получаем через параметр номер опроса
	$poll_id = (int) (!isset($_GET["id"]) ? -1 : 0 + $_GET["id"]);
	// если что-то не то, выходим
	if ($poll_id <= 0)
		exit;
	$sql = mysql_query("SELECT * FROM polls WHERE poll_id = $poll_id");
	// если ничего не выбралось, выходим
	if (!($sql && ($row = mysql_fetch_array($sql))))
		exit;
	// сохраним вопрос в переменную для дальнейшего использования
	$question = $row['question'];

	// IE блокирует чужие cookie (через iframe), добавляйте эту строчку, если будете их писать
	header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
?>
<!DOCTYPE html> 
<html lang="en"> 
<head> 
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<style type="text/css">
	<?php
		// если передан параметр цвет фона, то задействуем его
		if (isset($_GET['bg_color'])) {
			$bg_color = $_GET['bg_color'];
			echo "html,body { background: #$bg_color; }";
		}
	?>
	</style>
</head> 
<body onresize="resize_canvas()">
	<?php
		// выводим опрос с ответами
		echo "<h1>$question</h1>";
		$sql = mysql_query("SELECT * FROM answers WHERE poll_id_fk = $poll_id ORDER BY num ASC");
		if ($sql) {
			while ($row = mysql_fetch_array($sql)) {
				$answer = $row['answer'];
				echo "<p>$answer</p>";
			}
		}
	?>
	<script type="text/javascript">
		// этот скрипт сообщает родительскому окну высоту своего содержимого
		// с помощью механизма кросс-доменного обмена
		var parent_url = decodeURIComponent(document.location.hash.replace(/^#/, ''));
		function send(msg) {
			XD.postMessage(msg, parent_url, parent);
		}
		function resize_canvas() {
			send($('body').height());
		}
	</script>
</body>
</html>

Т.к. пример у нас обучающий, то мы не делаем процедуру голосования, вывод результатов и т.д.
В тексте скрипта, как может показаться, много всего сходу непонятного, но все вопросы снимутся по прочтению следующих шагов. Отметим здесь только обработчик onresize, который посылает при изменении размера страницы высоту в родительское окно.

Шаг 3. Создание скрипта для встраивания виджета на сайт

Сегодня стандартом де-факто для большинства виджетов является механизм встраивания через iframe.
Для этого есть ряд причин:
1. Владельцы сайтов, которые решили встроить ваш виджет не хотят, чтобы чужой код получал доступ к его содержимому (это как минимум небезопасно).
2. Встроить ваш виджет через iframe очень легко и не требует дополнительных навыков и знаний.
3. Из-за возможных ошибок в вашем коде может слететь верстка сайта, встраивающего ваш виджет.
4. Если вы храните в cookies какую-то информацию, например, идентификатор проголосовавшего, то при встраивании виджета через iframe данные будут храниться в привязке к URL сайта виджета (а не сайта, в который он встроен), что может быть полезно, например, если тот же самый опрос висит и на другом сайте. Человек уже проголосовавший один раз будет и на другом сайте видеть свой ответ, а не голосовать каждый раз заново.
и т.д.

Создадим функцию, которая будет внедрять на странице сайта наш виджет. Обратите внимание, в код зашиты два идентификатора (для простоты чтения, их можно вынести как параметры). Это widget_container — контейнер, внутри которого будет создан фрейм, и сам фрейм widget_iframe.

function createWidget(config) {
	var Util = {
		extendObject: function(a, b) {
			for(prop in b){
				a[prop] = b[prop];
			}
			return a;
		},
		proto: 'https:' == document.location.protocol ? 'https://' : 'http://'
	}

	var options = Util.extendObject({
		id: 0,
		domain: "example.com",
		bg_color: "FFFFFF"
	}, config);

	options.widget_url = [Util.proto, options.domain, "/?", "id=", options.id, "&bg_color=", options.bg_color].join("");
	options.widget_url += "#" + encodeURIComponent(document.location.href);

	Widget = {
		created: false,
		widgetElement: null,
		show: function() {
			if (this.created)
				return;
			this.widgetElement = document.createElement('div');
			this.widgetElement.setAttribute('id', 'widget_container');
			this.widgetElement.innerHTML = ' 
				<iframe id="widget_iframe" src="' + options.widget_url + '" scrolling="no" width="100%" height="0" frameborder="0"></iframe>';

			document.body.insertBefore(this.widgetElement, document.body.nextSibling);
			this.widgetElement.style.display = 'block';
			this.created = true;
		}
	}

	XD.receiveMessage(function(message) {
		if (message.data > 0 && document.getElementById("widget_iframe"))
		{
			document.getElementById("widget_iframe").height = message.data;
		}
	}, Util.proto + options.domain);

	Widget.show();
}

createWidget(widgetOptions);

Внутри функции описывается несколько объектов:
Util — помогает работать с параметрами.
Widget — сам объект нашего встраиваемого виджета.
XD — объект кросс-доменного обмена сообщениями (см. шаг 4, п. 2).

Как видно из кода, сначала создается элемент DIV, потом внутри него создается IFRAME, в который загружается страница с заданными в скрипте параметрами (по умолчанию это example.com/?id=0&bg_color=FFFFFF). Также устанавливается обработчик событий (получение сообщений от фрейма), который меняет высоту элемента, в данном случае растягивает виджет по высоте его содержимого.

Шаг 4. Решение проблем отображения

При встраивании виджета через iframe возникают определенные трудности.

1. Т.к. по сути в виджете загружен отдельный html-документ, то хочется как-то в него передавать свои настройки. Актуальным вопросом здесь являются стили, чтобы содержимое виджета вписывалось в дизайн сайта-потребителя. Можно реализовать передачу параметров через глобальную переменную, в нашем примере — это widgetOptions.

var widgetOptions = {
	id: 1,			// id опроса
	bg_color: 'FF0000'		// цвет фона
};

После того, как переменная объявлена, загружаем наш скрипт, создающий виджет:

(function() {
	var script = document.createElement('script');
	script.type = 'text/javascript';
	script.async = true;
	script.src = "http://example.com/widget.js";	// путь скрипта из шага 3
	document.getElementsByTagName('head')[0].appendChild(script);
})();

2. Есть проблема растягивания iframe по высоте его содержимого, чтобы не было никаких полос прокруток, а все смотрелось гармонично.

Для этого воспользуемся небольшим готовым скриптом:

Кросс-доменный обмен сообщениями

/* 
 * a backwards compatable implementation of postMessage
 * by Josh Fraser (joshfraser.com)
 * released under the Apache 2.0 license.  
 *
 * this code was adapted from Ben Alman's jQuery postMessage code found at:
 * http://benalman.com/projects/jquery-postmessage-plugin/
 * 
 * other inspiration was taken from Luke Shepard's code for Facebook Connect:
 * http://github.com/facebook/connect-js/blob/master/src/core/xd.js
 *
 * the goal of this project was to make a backwards compatable version of postMessage
 * without having any dependency on jQuery or the FB Connect libraries
 *
 * my goal was to keep this as terse as possible since my own purpose was to use this 
 * as part of a distributed widget where filesize could be sensative.
 * 
 */

// everything is wrapped in the XD function to reduce namespace collisions
var XD = function(){
  
    var interval_id,
    last_hash,
    cache_bust = 1,
    attached_callback,
    window = this;
    
    return {
        postMessage : function(message, target_url, target) {
            
            if (!target_url) { 
                return; 
            }
    
            target = target || parent;  // default to parent
    
            if (window['postMessage']) {
                // the browser supports window.postMessage, so call it with a targetOrigin
                // set appropriately, based on the target_url parameter.
                target['postMessage'](message, target_url.replace( /([^:]+://[^/]+).*/, '$1'));

            } else if (target_url) {
                // the browser does not support window.postMessage, so set the location
                // of the target to target_url#message. A bit ugly, but it works! A cache
                // bust parameter is added to ensure that repeat messages trigger the callback.
                target.location = target_url.replace(/#.*$/, '') + '#' + (+new Date) + (cache_bust++) + '&' + message;
            }
        },
  
        receiveMessage : function(callback, source_origin) {
            
            // browser supports window.postMessage
            if (window['postMessage']) {
                // bind the callback to the actual event associated with window.postMessage
                if (callback) {
                    attached_callback = function(e) {
                        if ((typeof source_origin === 'string' && e.origin !== source_origin)
                        || (Object.prototype.toString.call(source_origin) === "[object Function]" && source_origin(e.origin) === !1)) {
                            return !1;
                        }
                        callback(e);
                    };
                }
                if (window['addEventListener']) {
                    window[callback ? 'addEventListener' : 'removeEventListener']('message', attached_callback, !1);
                } else {
                    window[callback ? 'attachEvent' : 'detachEvent']('onmessage', attached_callback);
                }
            } else {
                // a polling loop is started & callback is called whenever the location.hash changes
                interval_id && clearInterval(interval_id);
                interval_id = null;

                if (callback) {
                    interval_id = setInterval(function(){
                        var hash = document.location.hash,
                        re = /^#?d+&/;
                        if (hash !== last_hash && re.test(hash)) {
                            last_hash = hash;
                            callback({data: hash.replace(re, '')});
                        }
                    }, 100);
                }
            }   
        }
    };
}();

Из фрейма с нашим виджетом будем посылать его высоту (при инициализации и при изменении размера окна) в родительское окно. Скрипт на странице с виджетом будет получать это значение и растягивать окно с виджетом по высоте его содержимого.

<body onresize="resize_canvas()">
	<script type="text/javascript">
		var parent_url = decodeURIComponent(document.location.hash.replace(/^#/, ''));
		function send(msg) {
			XD.postMessage(msg, parent_url, parent);
		}
		function resize_canvas() {
			send($('body').height());
		}
	</script>
</body>

Шаг 5. Оптимизация и релиз

После того, как наш виджет сделан, хорошим тоном считается минимизировать javascript код, чтобы не было сильного увеличения времени загрузки сайта-потребителя, а также для уменьшение трафика самого сайта виджета.
Подробнее об этом можно почитать в статье на Хабре Оптимизация Javascript с помощью Google Closure Compiler.

Если у вас полезный виджет, которым пользуются многие сайты, рекомендую поддержать https протокол, чтобы пользователям, выбравшим защищенное соединение, не отображалось сообщение о содержании небезопасного контента.
В скрипте для вставки вашего виджета строка пути теперь будет выглядеть следующим образом:

script.src = (document.location.protocol == "https:" ? "https:" : "http:") + "//example.com/widget.js";

P.S.

Исходников данного примера нет, поэтому не могу их выложить. Если кто-то на основе этой статьи соберет готовый проект и захочет им поделиться — wellcome!

Автор: StanSemenoff

Источник

Создание веб виджета для сторонних сайтов

Перед тем как продолжить ознакомление с данным материалом давайте немного поговорим о том, что такое виджет, где и для чего он используется.

Виджет — это небольшой независимый программный модуль, работающий в некоторой среде (напр. сайте, браузере, мобильном телефоне) и исполняющий, как правило, одну определённую функцию.

Вы наверное видели на страницах сайтов такие элементы, как:

  • информеры погоды, времени, курс валют;
  • онлайн тесты;
  • онлайн чаты
  • онлайн консультанты;
  • социальные виджеты, дающие возможность пользователем быстро и просто сделать репост понравившийся страницы сайта в своих социальных сетях;
  • подключение сервисов Яндекс.Метрика или Google Analytics к Вашему сайту по своей сути тоже является подключением виджета стороннего сервиса.

Таким образом, большинство из этих элементов на сайтах являются виджетами.
Виджеты служат не только украшением, они несут в себя информационный контент, и служат дополнительным инструментом для расширения функциональности сайта.

На текущий момент большое количество сервисов предоставляют для сторонних сайтов свои виджеты, которые выполняют определенные функции.
Во время установки виджета должны выполняться следующие требования:

  • установка виджетов не должна вызывает особых сложностей;
  • если дизайн виджета не подходит к общей стилистики сайта, то должна быть возможность его изменения.

Теперь давайте поставим для себя задачу.

Мы хотим создать виджет для сторонних сайтов, который будет отображать на их страницах, некий информационный блок с ссылками на наш сайт, т.е. создадим что то типо новостной ленты.
При этом встраивание нашего виджета на страницы сайтов должно быть очень простым.

На данном сайте мной реализован виджет, который формирует в правой колонке список ссылок на материалы раздела Яндекс.Карты.
В качестве демонстрации результата работы виджета Вы можете разместить на своем сайте следующий код:

скопируйте и вставьте следующий код на своем сайте

<div id="wrgsv"></div>
<script src="//resource-gsv.ru/assets/widget/widget.js" type="text/javascript"></script>
<script type="text/javascript">wrgsv.init();</script>

Подготавливаем файлы, необходимые для создания веб виджета

При создании веб виджета для сторонних сайтов, в качестве примера я буду использовать сайт с доменным именем yoursite.loc.
Для более полного понимания материала на момент создания нашего виджета, что бы не путаться в путях давайте создадим и разместим новые файлы прямо в корень сайта yoursite.loc,
там где расположен индексный файл.

Создадим в корне сайта 3 файла:

  • yoursite.loc
    • .htaccess
    • index.php
    • widget.php
    • widget.css
    • widget.js

widget.php

<ul>
    <li><a href="#"> link 1 </a></li>
    <li><a href="#"> link 2 </a></li>
    <li><a href="#"> link 3 </a></li>
</ul>

В нашем примере мы будем использовать статическую HTML разметку, так как нас интересует сам принцип создания веб виджетов.
Вы же, уже при создании рабочего виджета напишете код для получения тех данных, что Вам необходимы

widget.css

ul{
border: 1px solid RED;
}

внесем минимум стилей

widget.js

// ...

содержимое javascript файла на данные момент оставим пустым

Ознакомившись с механизмами работы веб виджетов мной было выявлено 2 метода встраивания их кода на страницы сайтов: используя элемент iframe и используя javascript.

Подключение виджета через iframe

Элемент iframe позволяет нам вставить один html-документ в другой html-документ, где в атрибуте src мы указываем путь к документу, который отобразиться во встроенном iframe.
При этом css и js файлы, необходимо подключить в файле widget.php.

widget.php

<!--подключаем файл стилей-->
<link href="widget.css" rel="stylesheet">
<ul>
    <li><a href="#"> link 1 </a></li>
    <li><a href="#"> link 2 </a></li>
    <li><a href="#"> link 3 </a></li>
</ul>

Таким образом для размещения веб виджета на сторонних сайтах через iframe необходимо разместить в нужном месте на html-страницы iframe примерно следующего содержания:

<iframe src="http://yoursite.loc/widget.php" width="480" height="320" frameborder="0" allowfullscreen ></iframe>

Подключение виджета через javascript

Рассмотрев более детально примеры подключения виджетов сторонних сайтов стало понятно, что их подключение также возможно осуществить средствами javascript.

Я приведу Вам пару примеров такого подключения виджетов:

Пример №1

<script type="text/javascript" src="//yastatic.net/share/share.js" charset="utf-8"></script>
<div class="yashare-auto-init" data-yashareL10n="ru" data-yashareType="link" data-yashareQuickServices="vkontakte,facebook,twitter,gplus"></div>

YandexLike (блок “Поделиться”) — простой виджет социальных сетей, позволяющий пользователям социальных сетей создавать репосты понравившихся страниц сайтов.

Пример №2

<script type="text/javascript" src="//vk.com/js/api/openapi.js?121"></script>
<!-- VK Widget -->
<div id="vk_groups"></div>
<script type="text/javascript">
VK.Widgets.Group(
    "vk_groups",
    {mode: 0, width: "220", height: "400", color1: 'FFFFFF', color2: '2B587A', color3: '5B7FA6'},
    20003922
);
</script>

Виджет для сообществ с соответствующей группой или официальной страницей ВКонтакте. Виджет позволяет подписаться на новости сообщества, не покидая страницы.

При подключении виджетов выполняются примерно следующие шаги:

  • добавление на страницу блока в который будет размещен виджет (в том случае, если виджет визуально отображается для посетителей сайта);
  • подключение javascript файла, с сайта предоставляющего подключение виджета
  • подключение css файла, с сайта предоставляющего подключение виджета (если это необходимо)
  • инициализация виджета

Исходя из данных примеров, мы видим, что установка виджетов отвечает основному требованию — она не вызывает особых сложностей.
Нам необходимо разместить всего пару строк предоставляемого кода на своей странице и виджет «волшебным образом» заработает.

Того же хотим добиться и мы с Вами. Мы хотим, что бы, установка нашего виджета была такой же простой.
Так давайте попробуем сделать свою реализацию подключения нашего виджета и его инициализацию.

Составим код, который мы будем предоставлять для встраивания нашего виджета на страницу любого сайта.

Код подключения нашего виджета

<div id="wrgsv"></div>
<script src="http://yoursite.loc/widget.js" type="text/javascript"></script>
<script type="text/javascript">wrgsv.init();</script>
  • 1 стр: добавляем на страницу HTML-элемент c идентификатором «wrgsv», в этот элемент будет размещен виджет после его инициализации
  • 2 стр: подключение javascript файла, в котором описан javascript объект виджета
  • 3 стр: инициализация виджета

Инициализация виджета через javascript

Пришло время поработать с нашим файлов widget.js.
В нем мы создадим объект с свойствами и методами.
Основным интересующим нас методом будет метод инициализации виджета init.

widget.js

var wrgsv = { 
    // идентификатор HTML элемента в который будет размещен виджет 
    idBox: 'wrgsv', 
    // путь до страницы возвращающей виджет 
    url_wiget: 'http://yoursite.loc/widget.php', 
    // путь до страницы стилей виджета 
    url_style: 'http://yoursite.loc/widget.css', 
    // метод инициализации виджета 
    init: function(id) { 
        // если идентификатор отсутствует, то будем использовать 
        // идентификатор HTML элемента для размещения виджета по умолчанию (т.е. "wrgsv") 
        if (!id) { id = this.idBox; } 
        if (document.getElementById(id)) { 
            // подключаем стили виджета 
            this.addStyle(); 
            try { 
                // для кросс-доменного запроса создаем один из ниже указанных объектов 
                var XHR = ("onload" in new XMLHttpRequest())?XMLHttpRequest:XDomainRequest; 
                // создаем экземпляр объекта 
                var xhr = new XHR(); 
                // запрос на другой домен (асинхронный) 
                xhr.open('GET', this.url_wiget, true); 
                // событие отслеживает, что запрос был успешно завершён 
                xhr.onload = function() { 
                    // если существует ответ 
                    if (this.response) { 
                        // добавляем полученный ответ в HTML элемент 
                        document.getElementById(id).innerHTML = this.response; 
                    } 
                } 
                xhr.onerror = function() { console.log('onerror '+this.status); } 
                // отсылаем запрос 
                xhr.send(); 
            } catch(e) {} 
        } 
        // если на странице не существует HTML элемента с указаным идентификатором 
        // выводим сообщение: блок с идентификатором id="id" отсутствует 
        else { console.log('The specified block id="'+id+'" is missing'); } 
    }, 
    // метод подключения стилей виджета 
    addStyle: function() { 
        style = document.createElement('link'); 
        style.rel = 'stylesheet'; 
        style.type = 'text/css'; 
        style.href = this.url_style; 
        document.head.appendChild(style); 
    }, 
}; 

Так как подключение css стилей виджета осуществляется, в методе «addStyle» объекта «wrgsv»,
то из файла http://yoursite.loc/widget.php необходимо удалить подключение файла стилей «widget.css»,
которое мы добавили ранее при подключении виджета через iframe.

Для базового расширения функционала виджета, мы можем добавить возможность во время его инициализации, указать в качестве параметра, идентификатор HTML-элемента, в который будет встроен виджет.
Это видно в методе init: function(id) { … }.

Код подключения нашего виджета с указанием нового идентификатора «new_id_box»

<div id="new_id_box"></div>
<script src="http://yoursite.loc/widget.js" type="text/javascript"></script>
<script type="text/javascript">wrgsv.init('new_id_box');</script>

Ошибки во время выполнения кросс-доменного скриптинга

Во время инициализации виджета, а именно во время отправки ajax запроса на другой домен, в консоле браузера может возникнуть ошибка. К разных браузерах она звучит по разному. К примеру:

В Chrome — XMLHttpRequest cannot load http://yoursite.loc/widget.php. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://САЙТ-ГДЕ-ПОДКЛЮЧАЕТСЯ-ВИДЖЕТ.ru’ is therefore not allowed access

В Firefox — Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на http://yoursite.loc/widget.php. (Причина: отсутствует заголовок CORS ‘Access-Control-Allow-Origin’)

Обычно запрос XMLHttpRequest выполняет запрос только в рамках текущего сайта.
При попытке использовать другой домен/порт/протокол – браузер выдаёт ошибку.
Возникновение данной ошибки вполне «нормальное явление», так как разработчики данного стандарта побеспокоились о контроле безопасности.

Для исправления данной ошибки необходимо внести изменения в заголовки ответа сервера и тем самым разрешить такой запрос для стороннего сайта.
Это можно сделать как минимум следующими способами:

  • Внести изменения в файл http://yoursite.loc/widget.php

    разрешение для отдельного домена (http://САЙТ-ГДЕ-ПОДКЛЮЧАЕТСЯ-ВИДЖЕТ.ru)

    <?php
    header('Access-Control-Allow-Origin: http://САЙТ-ГДЕ-ПОДКЛЮЧАЕТСЯ-ВИДЖЕТ.ru');
    // ...
    

    разрешение для всех доменов

    <?php
    header('Access-Control-Allow-Origin: *'); 
    // ...
    
  • Внести изменения в файл http://yoursite.loc/.htaccess

    разрешение для отдельного домена (http://САЙТ-ГДЕ-ПОДКЛЮЧАЕТСЯ-ВИДЖЕТ.ru)

    <IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin: http://САЙТ-ГДЕ-ПОДКЛЮЧАЕТСЯ-ВИДЖЕТ.ru
    </IfModule>
    

    разрешение для всех доменов

    <IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
    </IfModule>
    

Виджеты на сайте помогают решать разнообразные задачи бизнеса: сбор данных, повышение конверсии, информирование посетителей и многое другое. В этой статье разберем, что такое виджет, какими они бывают, как их создавать и добавлять на сайт.

Содержание:

  • Что такое виджет и зачем он нужен
  • Разновидности виджетов для сайта
  • Как добавить виджеты на сайт
  • Заключение

Что такое виджет и зачем он нужен

Виджет — это небольшое приложение, которое устанавливают на сайт в дополнение к основному функционалу. Визуально отображается на экране в виде интерактивного блока.

Когда нужно добавить новые возможности, модернизация сайта с помощью разработчиков может оказаться затратным и сложным делом. В таком случае проще использовать виджеты.

Виджеты на странице сайта привлекают внимание и помогают удержать пользователя. Например, поп-ап с выгодным предложением, всплывающий, когда посетитель собирается закрыть вкладку, или встроенные ролики с YouTube.

Этот инструмент способствует увеличению заявок и конверсий. Интерактивные значки обратного звонка, онлайн-чата или мессенджера напоминают о себе посетителю и подталкивают его к общению с менеджерами. Встроенные отзывы из различных источников, калькулятор и таймер обратного отсчета помогают быстрее принять решение. Иногда для этого используется виджет с имитацией очереди из клиентов.

Виджеты упрощают взаимодействие с сайтом, с помощью них удобно сообщить пользователям всю нужную информацию: местоположение офиса на Google картах, тарифы и цены в таблице, разные оповещения. Встроенные публикации из Инстаграм позволяют увидеть контент без перехода в соцсеть, а для тех, кто хочет подписаться на социальные сети компании, тоже имеются соответствующие виджеты.

Разновидности виджетов для сайта

Существует много разных виджетов, практически под любые потребности. Разберем наиболее полезные и популярные.

Чат-бот

Чат-бот — незаменимый помощник при ведении бизнеса. Если менеджер долго не отвечает на вопрос в онлайн-чате, клиент не захочет ждать и уйдет к конкурентам. Чат-бот на связи 24/7.

Инструмент позволяет автоматизировать часть этапов воронки продаж и доводить до менеджера только заинтересованных в покупке посетителей. В ряде случаев через чат-бот даже можно принимать оплату.

Этот инструмент используют для сбора данных пользователей и получения информации из внешних систем с помощью запроса API, но эта функция реализована далеко не во всех чат-ботах.

В SendPulse есть чат-боты для Telegram, Instagram, Facebook и WhatsApp. Их функционал несколько различается, но основные функции доступны во всех ботах.

По умолчанию подключена приветственная серия сообщений, которая приходит пользователю после подписки на бота. Стандартный ответ сработает, если на входящее не прописана конкретная команда. Также есть сообщение после отписки. Все цепочки можно откорректировать или же создать новые вручную. Переменные позволяют персонализировать рассылку.

В сообщение можно добавить кнопки: для перехода к следующему сообщению, с внешней ссылкой или с оплатой. После клика на последнюю клиент окажется на странице выбранной платежной системы и сможет быстро оплатить заказ. Сейчас доступны PayPal, Fondy и Stripe.

Настройка оплаты в чат-боте SendPulse
Настройка оплаты в чат-боте SendPulse

Чат-бот сохраняет данные, которые вводят пользователи в специально отведенные поля, и выдает сообщение об ошибке, если данные указаны некорректно.

Можно сегментировать подписчиков бота с помощью фильтра или путем присвоения тега и делать более целевые рассылки. Также доступна сегментация в настройках рассылки по дате или заданным условиям.

Блок «Действие» позволяет:

  • установить переменную для последующей фильтрации аудитории;
  • открыть чат с менеджером — в случае, если посетителю нужна персональная консультация;
  • отписать пользователя от бота;
  • добавить и убрать тег;
  • создать сделку и добавить ее в CRM — для этого требуется интеграция чат-бота с CRM-системой;
  • отправить вебхук — то есть передать информацию о событии в систему для дальнейшей работы с клиентом.
Возможности блока «Действие»
Возможности блока «Действие»

C помощью блока «Запрос API» можно быстро отправлять и получать информацию из внешних систем: например, найти данные о товаре в каталоге или зарегистрировать пользователя на мастер-класс. Подробнее об этом функционале — в базе знаний.

Различия чат-ботов обусловлены особенностями соцсетей. Например, в Телеграм-боте можно прикреплять аудио- и видеофайлы, а для чат-ботов в Инстаграм и Фейсбук предусмотрены карточки товаров с кнопкой оплаты внутри.

В SendPulse виджеты подписки многоканальные — легко подключить их для нескольких соцсетей и мессенджеров или сразу для всех.

Настройка виджета сайта: выбор формы
Настройка виджета сайта: выбор формы

В SendPulse можно управлять чатами с подписчиками ботов во всех мессенджерах через единый чат. Это экономит время и помогает держать все под контролем.

Рекомендуем к прочтению:

  • «Как легко создать бота в Telegram для своего бизнеса»;
  • «Чат-боты в Facebook Messenger для бизнеса: как начать их использовать прямо сейчас»;
  • «Как создать чат-бота в Инстаграм для бизнеса»;
  • «Что такое WhatsApp бот, чем он полезен и как его создать — полный пошаговый гайд»;
  • «Учимся создавать приветствие чат-бота. Важные правила и примеры из жизни»;
  • «Пишем текст для чат-бота: особенности и советы»;
  • «Примеры чат-ботов: удачные решения, которые можно использовать в бизнесе»;
  • «Как SendPulse создавал своего чат-бота. Делимся лайфхаками и советами».

Обратный звонок

Потенциальный клиент заинтересовался продуктом и хочет обсудить условия, но рабочий день закончился, или он сам занят на данный момент — для таких случаев на сайте стоит разместить виджет обратного звонка. Обычно он выглядит как небольшой кружок в правой части экрана, внутри которого значок телефона. При нажатии открывается форма для сбора данных, куда можно вписать свой номер и дополнительную информацию.

Пример виджета обратного звонка
Пример виджета обратного звонка

Этот инструмент помогает не упустить клиентов. Чтобы получить больше лидов, можно пообещать скидку тому, кто оставит свой номер в течение минуты, например.

Существуют разные модификации Callback виджета. В некоторых сервисах после того, как пользователь отправил свой номер, на устройстве менеджера автоматически начинается набор. Так клиенту не приходится долго ждать, что влияет на его отношение к компании.

Pop-up

Поп-ап представляет собой всплывающее окно с оповещениями: об использовании cookies, о выгодных акциях и промокодах, с предложением подписаться и так далее. Такие виджеты помогают заинтересовать посетителя и подтолкнуть его к целевому действию, способствуют увеличению времени нахождения на сайте и росту конверсий. Можно настроить появление оповещений через определенное время или при попытке покинуть страницу.

Пример Pop-up виджета на странице сайта
Пример Pop-up виджета на странице сайта

Поп-апы не должны занимать много пространства и быть навязчивыми. Сделайте так, чтобы их легко можно было убрать — иногда элемент закрытия плохо видно, или окно выскакивает несколько раз, это сильно раздражает.

В дизайне поп-апа стоит использовать яркие цвета, чтобы сделать его заметным. Полезно также оценить его влияние на посетителей, например, при помощи фокус-групп. Наверняка вы видели оповещения о том, что «стали победителем розыгрыша призов на сайте» — постарайтесь максимально отойти от такого оформления, из-за которого хочется сразу закрыть сайт.

Рекомендуем к прочтению: «Всплывающие окна на сайте для сбора контактов: как использовать их грамотно».

Онлайн-чат

Если у вас нет большого наплыва клиентов, вместо чат-бота можно попробовать онлайн-чат. Если у посетителей сайта возникнут вопросы, они напишут сообщение, и менеджер их проконсультирует.

Полезно добавить виджет на сайт, чтобы клиенты могли задавать вопросы
Полезно добавить виджет на сайт, чтобы клиенты могли задавать вопросы

Обычно у таких виджетов есть возможность вести переписку как через личный кабинет, так и с помощью отдельных приложений. Иногда у менеджера отображаются страницы, просмотренные пользователем.

Для таких виджетов обычно доступны интеграции с системами аналитики и CRM.

Виджеты соцсетей и мессенджеров

Если вы развиваете социальные сети компании, можно использовать их виджеты для сайта. Это поможет набрать больше подписчиков и успешно продвигать аккаунты в соцсетях, что положительно скажется на продажах.

Виджет соцсетей можно разместить на главной странице, в разделе «О нас», на странице с контактами, в футере.

Виджет для сайта с публикациями из Инстаграм-аккаунта
Виджет для сайта с публикациями из Инстаграм-аккаунта

Виджеты мессенджеров будут полезны, если в них происходит основное общение менеджеров с клиентами. Если пользователю не нужно искать номер компании на сайте и потом вводить его на телефоне, а можно написать сразу — это повышает шансы на получение заявки.

Для быстрой связи добавьте виджеты на сайт для мессенджеров
Для быстрой связи добавьте виджеты на сайт для мессенджеров

Виджет email подписки

С помощью такого виджета можно увеличить базу подписчиков email рассылки. Email маркетинг — эффективное средство для стимулирования продаж, удержания клиентов и повышения лояльности. Посмотрите статистику в нашей статье, чтобы убедиться в этом.

Пример виджета подписки на email рассылку
Пример виджета подписки на email рассылку

Форму подписки можно создать в сервисе SendPulse. Она может быть плавающая, встроенная, фиксированная или в формате поп-апа. Для удобства добавлено несколько готовых шаблонов.

Создание формы подписки в SendPulse
Создание формы подписки в SendPulse

Калькулятор

Виджеты-калькуляторы полезны в сферах, где нужны предварительные расчеты: например, магазины строительных материалов и стройфирмы, сервис клининга, пошив одежды, логистика и так далее.

Пример виджета-калькулятора
Пример виджета-калькулятора

Калькулятор помогает удержать пользователей на сайте, усилить интерес к продукту и получить больше заявок.

Google карты

Если у вас есть офлайн-точки, используйте виджет Google карт с возможностью построить маршрут. Чем больше на сайте контактной информации, тем больше посещений в офлайне. Наличие реального офиса, в который можно прийти, укрепляет представление о надежности бизнеса.

Виджет на страницу сайта с Google картами
Виджет на страницу сайта с Google картами

Разместите список адресов с указанием телефона и режима работы, если точек несколько — так клиенты смогут выбрать наиболее удобный для них.

Отзывы

Наличие отзывов внушает доверие и способствует продажам. Но пользователи должны видеть, что их пишут реальные люди. Для этого интегрируйте на сайт отзывы с Google, Facebook, AliExpress, Apple Store и других площадок. Так потенциальные клиенты смогут узнать мнение состоявшихся покупателей, посмотреть информацию о них и убедиться, что оценки не куплены.

Виджет для сайта с отзывами из Google
Виджет для сайта с отзывами из Google

В таких виджетах доступны фильтры, с помощью которых можно настроить показ так, как вам хочется: только положительные отзывы, от конкретных авторов и так далее. Формат слайдера используется, когда блок с отзывами размещают в зоне контента. Формат сетки — когда для них отведена отдельная страница.

Советуем ознакомиться: «Как отвечать на негативные отзывы клиентов».

Таймер

Обратный отсчет создает эффект срочности, придает ценности продукту в представлении посетителей и подталкивает их к совершению покупки.

Например, вы устроили распродажу, и скидки действуют только до конца дня. Разместите виджет с таймером и напишите, что в ближайшее время такие щедрые предложения не планируются. Только не стоит обманывать пользователей и запускать таймер снова и снова, иначе эффект срочности перестанет работать.

Виджет обратного отсчета можно использовать для создания праздничной атмосферы, как в примере ниже. Напоминание о празднике стимулирует к поиску подарков и новым покупкам.

Таймер с отсчетом до наступления Нового года
Таймер с отсчетом до наступления Нового года

Как добавить виджеты на сайт

Виджеты формируются с помощью JavaScript‑кода, который вставляется в нужном месте в HTML-код сайта.

Для сайтов на WordPress предусмотрены стандартные виджеты, которые можно добавить через панель управления в настройках внешнего вида. Если этих виджетов недостаточно, можно найти и установить подходящий плагин.

В конструкторах сайтов, например, например, Wix, можно размещать блоки с виджетами: онлайн-запись, чат, соцсети, виджет товара и так далее.

Добавление виджета в конструкторе Wix
Добавление виджета в конструкторе Wix

Создать и добавить виджеты на сайт удобно с помощью специальных сервисов, например, Elfsight. Алгоритм примерно одинаковый. Вы создаете свой виджет с нуля или на основе готового шаблона. Сервис выдает код, который требуется вставить в структуру сайта. Обычно для этого нужно открыть настройки блока интернет-страницы, добавить блок HTML и вставить код виджета в соответствующее поле. Затем сохранить настройки и опубликовать страницу.

В нашей базе знаний можно прочитать о том, как создать в SendPulse виджет подписки на чат-бота и добавить его на сайт.

Пример кода для установки виджета подписки на чат-бота от SendPulse
Пример кода для установки виджета подписки на чат-бота от SendPulse

Заключение

Мы разобрали, как установить виджеты на сайт и зачем это нужно. Расширяйте функционал сайта с их помощью, расширяйте клиентскую базу и увеличивайте конверсию.

Рекомендуем добавить виджет чат-бота SendPulse для автоматизированной обработки заявок. Также советуем попробовать другие наши инструменты: сервисы email, SMS и Viber рассылок, удобный конструктор лендингов и мультиссылок, сервис web push уведомлений и бесплатную CRM-систему.

WordPress widgets are incredibly useful. They let you add all kinds of extra content to your website outside the body of the post or page itself, encouraging users to get information, follow links, or take action.

In this post, I’m going to show you everything you need to know about WordPress widgets. How to add them to your site, how to create widget areas to put them in, how to install plugins that give you more of them, how to code your own widgets, and lots more.

First, let’s start by identifying what WordPress widgets are.

What are WordPress widgets?

In WordPress, widgets are snippets of content that live outside the flow of the page or post content.

Widgets contain information, navigation or media that is separate from an individual post or page. In most cases, each widget will be displayed on every page in the site, but you can also register widget areas for specific pages such as the home page.

To add a widget to your site, you need to add it to a widget area. Widget areas are created by your theme because they relate to the design and layout of your site and not to functionality.

Most WordPress themes have widget areas in the sidebar and footer, although some will have multiple widget areas in lots of places, such as below or above the content or in the header.

The screenshot below, of one of my own sites, shows widgets in the sidebar and footer.

Widget areas in my site

Widget areas in my site

WordPress comes with a bunch of widgets preloaded so you can use them without having to install any plugins or write any code. But you can also add lots more widgets by installing plugins or coding your own.

These can cover a vast range of content types, such as media, social media feeds, navigation, search, maps and lots more. There’s very little you might want on your site that you can’t find a widget for. In fact, the biggest challenge is often choosing between all the options and not going overboard.

When to Use WordPress Widgets

You should use a widget whenever you want to add extra content to one or more pages in your site (and when I say page, I include posts, archives etc.), but that isn’t part of the content of that page. They’re particularly useful for content you want to show on every page of the site, such as a list of your latest posts, a shopping cart, or a call to action button.

Think about how many users will need access to each widget and how important it is when you decide where to place it. Widgets in the sidebar will be more prominent than those in the footer, which some users may not even see.

So a latest posts widget or a call to action widget might be better off in the sidebar where people have more chance of interacting with them, while a social media feed could go in the footer.

If your theme also has special widget areas for the home page, you might want to use these for navigation around your site’s departments, lists of relevant content, or media such as a video welcoming people to the site.

11 Examples of Widgets in WordPress

The best way to understand the possibilities offered by WordPress widgets is by looking at some examples of them. Let’s take a look at eleven types of widget you’ll frequently see on WordPress sites.

1. Recent Posts Widget

The Recent Posts widget is possibly the most commonly used widget in blogs.

It lets you display a list of your most recent posts in the sidebar or footer of every page on your site, increasing the possibility that people will browse the site and read a number of posts.

The Recent Posts widget comes pre-installed with WordPress. It lets you set how many posts you want to show and what heading you want to give the widget.

Latest Posts widget

Recent Posts widget

If you want to add extra functionality, you can install a plugin for an alternative widget like WordPress Popular Posts, which displays the most popular content. Alternatively, the Advanced Random Posts widget refreshes every time the user visits a new screen.

2. Recent Comments Widget

Want to show visitors how vibrant your site is and how much your audience is engaging with your content?

The Recent Comments widget displays the latest comments on your site, giving visitors the opportunity to navigate straight to those comments and join in the discussion.

Recent Comments widget

Recent Comments widget

The Recent Comments widget comes with WordPress. Again, if you want to add extra functionality you can install a third-party comments plugin such as the WP Social Comments widget which lets people comment using their Facebook account: good for social media engagement.

3. Call to Action Widgets

A great use of a widget is to encourage people to take action, and you can do this with a call to action widget.

Your widget could be a simple button, or you could create something more bespoke using a text widget or HTML widget, or even an image widget, all of which come pre-installed with WordPress.

On one of my own sites, I’ve created a call to action widget encouraging people to sign up to my mailing list. This uses the built-in HTML widget in which I’ve included an image, some text and a button that I’ve coded in HTML.

Call to Action widgets on my site

Call to Action widgets on my site

4. Navigation Widgets

You can also use widgets to encourage people to navigate around your site.

There are a few options for this: the Categories or Tag Cloud widgets and the Navigation Menu widget.

The Navigation Menu widget lets you create an custom navigation  menu as well as the main navigation menu in your site, and then add that to a widget area.

You could even add your main navigation menu to a widget area, although this will only work if you have a small navigation menu.

Navigation Menu widget

Navigation Menu widget

Adding a navigation menu to the footer of your site will encourage people reaching the end of a post to navigate around your site. It’s particularly helpful for mobile users who may have to do a lot of scrolling to get back up to the main navigation menu after reaching the end of a post.

Alternatively, you can use the built-in Categories widget to display a list of the categories in your site, or the Tag Cloud widget to make it easy for people to access tag archives.

5. Media Widgets

Adding media to your sidebar or footer will bring your site to life and give users something to look at or interact with.

You can use the built-in Image widget to display any image in your sidebar or footer, and it lets you turn that image into a link too.

Image widget

Image widget

Alternatively, the Video widget lets you stream video from YouTube or Vimeo right into the widget area of your site. This is particularly useful if your site has special widget areas for the home page, but can also be good in the footer as a way of catching people’s attention when they reach the end of a post.

6. Social Media Widgets

If you want to engage with people who visit your website by social media, adding your social media feed to the sidebar or footer of your site will show people that you’re active on social media and encourage them to like or follow you.

One way to get access to social media widgets for the biggest platforms (Facebook, Twitter, Instagram) is to install the Jetpack plugin, which includes all of these and lots more.

Jetpack plugin

Jetpack plugin

Alternatively, all the social media platforms have their own plugins, available free via the plugin directory. Or you can find third party plugins that will let you customize the way you display your social media feed.

7. Shopping Cart Widget

If you’re running an ecommerce store on your site using a plugin like WooCommerce, it’s a good idea to include a cart widget so users can easily navigate to their cart wherever they are in the store.

Shopping cart widget

Shopping cart widget

You could put this in the sidebar where people will easily be able to see it, or in the header for added visibility if your theme includes a widget area there.

Ecommerce plugins like WooCommerce include shopping cart widgets and other e-commerce widgets as part of the plugin, so once you’ve added e-commerce to your site, you’ll find them added to your Widgets screen.

8. Form Widget

If you want people to contact you, ask questions or sign up to a mailing list, you could add a form to your sidebar.

There isn’t a form widget included with WordPress but you can add plugins to provide them, such as the free Contact Form 7 or the premium but very powerful Gravity Forms.

9. Map Widget

If your business is based in a physical location and you want people to be able to find you easily, adding a map widget to your site will help.

There are a number of free Google map widget plugins or other WordPress map plugins you can use, such as the WP Google Maps plugin.

WP Google Maps plugin

WP Google Maps plugin

Alternatively, if you don’t want to install a plugin, you can grab the embed code from Google Maps and add that to an HTML widget.

10. Login Widget

If you’re running a membership site, a login widget will make it easy for people to log into your site without having to go to a separate login page.

The Meta widget which comes with WordPress includes a login link but it also includes other things you might not want, so I’d recommend using a separate plugin for this from the plugin directory.

The Login with Ajax widget gives you a login form in your widget meaning people can log into your site from any page.

Login with Ajax widget plugin

Login with Ajax widget plugin

11. Search Widget

A really simple but incredibly useful widget is the Search widget, which comes preloaded with WordPress.

Search widget

Search widget

Add this to your sidebar or header and you make it easier for people to find things on your site.

If you want to boost the power of your search widget, you can install the free WP Google Search widget, which uses Google search.

How to Add Widgets to your WordPress Site

Once you’ve decided what kind of widgets you need for your WordPress site, it’s time to install them.

Don’t be tempted to add too many. The more there are, the less likely users are to notice them. Instead, focus on two or three key widgets for the sidebar. You can add more to the footer, where they’re less important anyway.

And if you have any extra widget areas in your theme, decide which widgets to put in those. Make sure they fit with the layout and design of your site.

There are three ways to add widgets:

  • Use the widgets that already come with WordPress.
  • Add a third-party widget from the plugins directory.
  • Buy a premium plugin that includes a widget.

Finding Widgets for Your WordPress Site

There is a vast array of available widgets, so it can bed difficult to choose which one to install. Let’s take a look at the options and then examine how you might choose the best one for you.

Widgets that come with WordPress

If one of the pre-installed widgets does what you need it to, then use that. It will save you time and mean less code running on your site.

Pre-installed WordPress widgets

Pre-installed WordPress widgets

The pre-installed widgets are:

  • Archives: link to archives by month, designed for blogs but rather outdated now.
  • Calendar: a calendar of your posts, again suitable for blogs especially if yours is time-sensitive (but not so common these days).
  • Custom HTML: the ultimate in flexibility, add whatever content you want by typing or pasting in the HTML (like Google forms). Avoid if you aren’t comfortable with coding.
  • Image: display an image from your media library.
  • Navigation Menu: show the main navigation menu or a separate one you create.
  • Recent Comments: a list of recent comments with links to them.
  • Tag Cloud: a list of tags in a cloud format, with links to the relevant archives.
  • Video: embed a video from YouTube or any other streaming service.
  • Audio: embed a podcast, a player, song or other audio clips (suggested: How to Start a Podcast Using WordPress).
  • Categories: a list of the categories in your blog, with links to the archive pages.
  • Gallery: more advanced than the image widget, display a gallery of images.
  • Meta: metadata such as login links and RSS feeds. A hangover from WordPress’s early days and not very useful now.
  • Pages: show a list of your site’s pages with links.
  • Recent Posts: display a list of your most recent posts to encourage people to read them.
  • Search: a simple search box.
  • Text: any text you want to add, such as information about the site.

Adding Widgets with a Plugin

The WordPress plugin directory has thousands of free widget plugins that will give you more widgets to choose from.

As well as that, lots of other plugins also include widgets, such as an ecommerce plugin giving you a cart widget and more.

If the plugin directory doesn’t have the plugin you need, you might decide to add a premium plugin. Sometimes these will offer more functions or a more intuitive interface. But sometimes you’ll find the same features in a free plugin, so make a good search of the plugin directory before paying for plugins.

How to Find the Right Widget for Your Site

To find the right WordPress widget for you, follow these tips:

  1. Identify exactly what you need from the widget. What functionality does it need to have and how do you want it to look? Does it need to link to any third-party APIs?
  2. Check the built-in widgets to see if there’s one that meets your needs. Test any relevant ones, if you find a suitable one, that’s great. If not…
  3. Check the plugin directory, which you can access via Plugins > Add New. Try searching for more than one term to find the right plugin for you, and search with and without the word ‘widget’. Sometimes a plugin that isn’t focused on widgets will include a widget as part of a wider set of features.
  4. If you can’t find anything suitable among the free plugins, look for a premium plugin. Ask other WordPress users for recommendations and look at reviews before choosing one.

Whichever widget you choose, you’ll need to test it to check it works as you want it to. If you’re buying premium plugins, I’d recommend buying one with a money-back guarantee or a free trial period in case it isn’t right for you.

How to Add Widgets to the Sidebar and Footer in WordPress

Now you’ve chosen your widget, it’s time to add it to your site.

You can add widgets to any active widget areas provided by your theme. If your theme doesn’t have a widget area in the place you want one, try looking for an alternative theme.

Later in this post I’ll show you how to code your own widget area.

There are two ways to add widgets to your site:

  • By using the Customizer. Go to Appearance > Customizer > Widgets in the admin menu, or Customize > Widgets from the admin bar at the top of the screen.
  • Via the Widgets admin screen. Go to Appearance > Widgets in the admin menu, or from the admin bar, click Customize > Widgets.

Widgets in the Customizer

Widgets in the Customizer

I’ll show you how to use both of these methods shortly but first let’s have a look at widget areas and why you get the ones you do with your theme.

Widgets Aren’t Just for the Sidebar

Depending on your WordPress theme, you might find you have widget areas in multiple places.

Most themes have widget areas in the sidebar and footer. But some also have them in other places, like below or above the content or in the header.

If you go to the widgets settings screen in the WordPress admin, you’ll be able to see all of the widget areas in your theme.

I use a theme with multiple widget areas in lots of places. You can see in the screenshot below that there are widget areas above and below the content, in the header, below the main footer.

Widgets setting screen, widget areas

Widgets setting screen, widget areas

If you want to add widgets to other places in your site it makes sense to find a theme that has multiple widget areas. The best way to do this is to use a framework theme.

A good example of a widget in a place in your theme that isn’t the sidebar or the footer is to add a search bar in the header like I have on one of my websites.

Search bar in the header

Search bar in the header

Widget Areas and Themes

Widget areas are coded into the theme template files, as well as the theme functions file.

Here you can see the code I’ve used in my theme functions file to add a widget area that will go in the header.

register_sidebar( array(
 'name' => __( 'In Header Widget Area', 'rmccollin' ),
 'id' => 'in-header-widget-area',
 'description' => __( 'A widget area located to the right hand side of the header, next to the site title and description.', 'rmccollin' ),
 'before_widget' => '<div id="%1$s" class="widget-container %2$s">',
 'after_widget' => '</div>',
 'before_title' => '<h3 class="widget-title">',
 'after_title' => '</h3>',
) );

And here is the code in my header.php file that adds that widget area into the right place in the theme.

if ( is_active_sidebar( 'in-header-widget-area' ) ) { ?>

 <aside class="in-header widget-area right" role="complementary">
  <?php dynamic_sidebar( 'in-header-widget-area' ); ?>
 </aside>

<?php }

If you want to add extra widget areas in your theme, you need to add the same kind of code. I’ll show you how to do this later in this post.

Don’t forget that if your theme doesn’t have as many widget areas as you would like, you can always do one of two things:

  • Find a theme that does have widget areas where you want them.
  • Code the new widget area into your theme or a child of your theme.

Once you’ve got widget areas in all the places in your theme that you want them, you can start adding widgets to them.

How to Use the Widgets Screen to add Widgets

There are two ways to add widgets to your WordPress site. The first one is to use the Widgets screen in the WordPress admin.

Click on Appearance > Widgets. This brings up the widgets screen.

Widgets screen

Widgets screen

To add a widget you can do one of two things:

  • Drag it over from the list of widgets on the left-hand side into the relevant widget area.
  • Click on the widget you want to add, and you’ll see a list of where you could add it. Select the widget area you want, and click the Add Widget button.

Selecting a widget area and widget

Selecting a widget area and widget

You might then need to edit where the widget is positioned within the widget area.

You can add as many widgets as you want to each widget area, but don’t go overboard. You can drag them around inside the widget area to get them in the right order. You can also drag them from one widget area to another if you decide you don’t like the way they look.

You can also use your keyboard to add widgets using the Widgets screen, so if you don’t have access to a mouse you can still add widgets.

Adding and Editing Widgets in Accessibility Mode

If you can’t use a mouse, you can use the Widgets screen with a keyboard.

First, put the screen into accessibility mode by clicking on (or tabbing to and selecting) the Enable accessibility mode link at the top right of the screen.

Accessibility mode link

Accessibility mode link

The screen will then change to reflect the fact that you’re in accessibility mode.

Widgets screen accessibility mode

Widgets screen accessibility mode

You can then navigate between elements of the screen using the Tab key on your keyboard, and hit Enter to select an item and act on it. You can either tab to a widget, hit Return on the Add link and then pick where you want to add it, or tab to the widget area and hit Return on the Edit link.

How to Use the WordPress Customizer to Add Widgets

Using the Customizer to add widgets instead of the widgets screen means you can see your widgets as you’re adding them. This makes it easier to see how your widgets will look and to move them around between widget areas if you want to.

In the admin menu, click Appearance > Customize. Alternatively, from the admin bar at the top of the screen in the live site (assuming you’re logged in), just click on Customize. This will open the Customizer.

WordPress admin bar

WordPress admin bar

Now click the Widgets option and you will see a list of all the widget areas in your theme. Click the widget area where you want to add a widget and click the Add a widget button.

This gives you a list of all the widgets available for your site. That’ll include all the built-in widgets that came with WordPress plus any widget you’ve added via plugins.

Add a widget button

Add a widget button

Pick the widget you want to add to that widget area and you’ll see it in the preview screen on the right-hand side.

You can reorder widgets by dragging them up and down on the left-hand side or by clicking the Reorder link below the list of widgets and then clicking the arrows to move them up and down.

Editing widgets in the Customizer

Editing widgets in the Customizer

Once you finished adding widgets via the Customizer don’t forget to click the Publish button at the top left so that your changes are saved. If you leave the Customizer without doing this, none of your changes will be reflected on the live site.

Once you added your widgets, please take a look at them and check how they fit in the design of your page. If you’ve added too many widget areas, things might look a bit messy. You’ll either need to remove some of them or you can move them from one widget area to another.

It’s really easy to do this in the Widgets screen, where you can drag widgets between widget areas.

How to Add a Widget to a Specific Page

Some themes include widget areas that are just for specific pages, like the homepage. But what if you want to add a widget to just one page on your site?

You can do this in the Gutenberg post and page editor.

Add a new block in the usual way and then select the Widgets block type.

Widget block type

Widget block type

You can then choose from many of the widgets you have enabled for your site, and add it to the content of your post or page. It’s really useful if you want to add a form widget, a call to action widget, or a list of your latest posts.

How to Edit Widgets

Once you’ve added widgets to your site, you can make changes to them. Individual widgets will have settings you can access via either the Widgets screen or the Customizer (it doesn’t matter which of these you used to add the widget.)

Some widgets don’t include any settings, but others have settings for the widget title for example or the number of posts displayed. Some are more complicated and require you to set up the widget in a separate settings page. Check the documentation from your plugin’s developer.

Options you have for editing widget plugins include:

  • Editing the settings for the plugin.
  • Moving the widget from one widget area to another.
  • Removing the widget. You have two options for this, which will look at shortly.

To edit the settings for the widget, find that widget in the widgets screen or the customizer, and simply edit any options provided.

Editing widget options

Editing widget options

To move the widget from one area to another, open the widgets screen and drag it from one widget area to another. In accessibility mode, navigate to the arrow to the right of the widget and select from the options.

Deleting Widgets

To delete a widget in the Widgets screen, find that widget and click the delete link to the bottom left of the widget settings box.

Deleting a widget in the widgets screen

Deleting a widget in the widgets screen

To delete a widget in the Customizer, find the widget in its widget area. Click on the arrow to the right of the widget’s name, and then click the Remove link to the bottom left of the widget settings.

Removing a widget in the Customizer

Removing a widget in the Customizer

You can also remove a widget from a widget area but still make it available to use later on through the Widgets screen.

Scroll down to the Inactive Widgets area towards the bottom of the screen. Drag widgets to this area to remove them from the widget area but keep them as drafts with their current settings. You can then always drag them back into a widget area if you want to in the future.

If you switch themes and your new theme has different widget areas, any widgets that don’t fit in the widget areas in the new theme will automatically be moved to the Inactive Widgets list by WordPress.

How to Add a New Widget Area to your Theme

If your theme doesn’t have widget areas where you want them, you can always add your own. You do this by adding two pieces of code.

Let’s add a widget area below the content.

Creating the Widget Area in Your Theme Functions File

The first step is to set up the widget area using the register_widget() function.

If you’re using a third-party WordPress theme (here’s a selection of the best ones), you need to create a child theme to do this. The reason for that is that if you update the theme in the future, all your changes will be lost.

If you’re working with your own theme, you can simply edit the theme.

Start by opening your theme’s functions.php file. At the bottom of the file, add this code.

function kinsta_register_widgets() {
 
 register_sidebar( array(
  'name' => __( 'After Content Widget Area', 'kinsta' ),
  'id' => 'after-content-widget-area',
  'description' => __( 'Widget area after the content', 'kinsta' ),
  'before_widget' => '<div id="%1$s" class="widget-container %2$s">',
  'after_widget' => '</div>',
  'before_title' => '<h3 class="widget-title">',
  'after_title' => '</h3>',

 ) );

}

add_action( 'widgets_init', 'kinsta_register_widgets' );

Now save your functions.php file. If you go to your Widgets screen or the Customizer, you’ll find the new widget area available for you to add widgets.

But if you do this, they won’t actually show up on the page. This is because you need to add some code to your theme template file.

Adding The Widget to a Theme Template File

The first thing is to find out which theme template file you need to use.

  • If you’re adding an extra sidebar, then you’ll need to add this code to your sidebar.php file.
  • If you’re adding your widget area before or after the content, you’ll need to add it to whichever theme template files are outputting the content.
  • If you’re adding a widget area to your header, you’ll need to add the code to your header.php file.
  • If your new widget area is just for one page in your site or for one type of content, you’ll need to use the WordPress template hierarchy to work out exactly which template file you need to either use/create and then edit it. So, for example, you’d like to add widget areas to your homepage, you’ll need to create a front-page.php file and add your widget area there.

Once you’ve identified which template file you need to edit and exactly where you need to have the code for the widget area, add the following code. In the case of a widget area after the content, we add it to the post.php and page.php file in our theme:

if ( is_active_sidebar( 'after-content-widget-area' ) ) { ?>

 aside class="after-content widget-area full-width" role="complementary">
  <?php dynamic_sidebar( 'after-content-widget-area' ); ?>
 </aside>

<?php }

Now save your template file(s).

Note that your code will be different from mine depending on what you’ve called your widget area and what elements you want to place it inside. I generally use an aside element because to my mind they are designed for sidebars and widget areas.

Ninja tip: If you move the ending of your container element for the content to the beginning of the sidebar and/or footer file, then you can add this there and you only need to add it once.

Now if you take a look at your site, you’ll find that any widgets you added to your widget areas will show up in the right place. If they’re not in quite the right place, go back and edit your template files, making sure the code is in the spot where you want it. You also might need to edit your CSS to get looking the way you want it to.

Widget on the live site

Widget on the live site

How to Code Widgets Using the Widgets API

So now you know how to pick widgets for your site, how to add them to your site, and how to register new sidebars or widget areas. The next step is to learn how to create a WordPress widget.

Sometimes, you might find there isn’t a plugin available to create the exact widget that you want on your site. That means you’ll have to code it yourself.

In this example, I’m going to show you how to code a really simple call-to-action widget.

Overview of the Widgets API

The Widgets API in WordPress includes all of the code that you need to register, create, and code widgets. The Widgets API includes:

  • Classes to build new widgets.
  • Functions to register widgets and deploy them on your site.
  • Functions to unregister widgets, for example from a parent theme.

Here we’ll be using a class to build a widget. The first step is to create a plugin to hold the widget.

Create a Plugin for Your WordPress Widget

To create your own widget, you’ll need to code a plugin. Don’t add the code for a new widget to your theme, because widgets are about functionality and not about display. If you change your theme in the future, you want to still be able to access that widget.

Start by creating an empty plugin. Create a plugin folder in your wp-content/plugins directory and add an empty file to that. Give it an appropriate name. Open that file and add this code.

<?php
/**
 * Plugin Name: Kinsta Call to Action Widget
 * Plugin URI: https://rachelmccollin.com
 * Description: A simple call to action widget.
 * Version: 1.0
 * Author: Rachel McCollin
 * Author URI: https://rachelmccollin.co.uk
 */

You’ll need to edit the author URI and plugin URI to your own. That will create a plugin for you that you can activate via the Plugins screen.

Widget plugin in plugins screen

Widget plugin in plugins screen

But if you activate it, nothing will happen. You’re going to have to add some code to your plugin.

Create a Class for the Widget

The code for the widget is going inside a class. So add that next.

class kinsta_Cta_Widget extends WP_Widget {

}

Create the Constructor Function

The first thing to go inside the class is the constructor function to create the widget. Add this inside the braces of the class.

//widget constructor function

function __construct() {

 $widget_options = array (
  'classname' => 'kinsta_cta_widget',
  'description' => 'Add a call to action box with your own text and link.'
 );

 parent::__construct( 'kinsta_cta_widget', 'Call to Action', $widget_options );

}

This starts to build the widget.

Create the Form to Output the Widget

Next, we need a form that will be used by the Widgets screen and the Customizer to create the widget. Add this, still inside the braces.

//function to output the widget form

function form( $instance ) {

 $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
 $link = ! empty( $instance['link'] ) ? $instance['link'] : 'Your link here';
 $text = ! empty( $instance['text'] ) ? $instance['text'] : 'Your text here';
?>

<p>
 <label for="<?php echo $this->get_field_id( 'title'); ?>">Title:</label>
 <input class="widefat" type="text" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo esc_attr( $title ); ?>" /></p>

<p>
 <label for="<?php echo $this->get_field_id( 'text'); ?>">Text in the call to action box:</label>
 <input class="widefat" type="text" id="<?php echo $this->get_field_id( 'text' ); ?>" name="<?php echo $this->get_field_name( 'text' ); ?>" value="<?php echo esc_attr( $text ); ?>" /></p>

<p>
 <label for="<?php echo $this->get_field_id( 'link'); ?>">Your link:</label>
 <input class="widefat" type="text" id="<?php echo $this->get_field_id( 'link' ); ?>" name="<?php echo $this->get_field_name( 'link' ); ?>" value="<?php echo esc_attr( $link ); ?>" /></p>

<?php }

This gives users a form they can use to add text and a link to the call to action box.

Create the Function to Save the Widget

Now you need to save anything that’s input to that form. Add this.

//function to define the data saved by the widget

function update( $new_instance, $old_instance ) {
 $instance = $old_instance;
 $instance['title'] = strip_tags( $new_instance['title'] );
 $instance['text'] = strip_tags( $new_instance['text'] );
 $instance['link'] = strip_tags( $new_instance['link'] );
 return $instance;          

}

This will save the data input by users to the widget settings.

Create the Function to Output the Widget

Now you need to add the code which will display the widget on the site. Again, add this inside the braces:

//function to display the widget in the site

function widget( $args, $instance ) {
 //define variables
 $title = apply_filters( 'widget_title', $instance['title'] );
 $text = $instance['text'];
 $link = $instance['link'];

 //output code
 echo $args['before_widget'];
 ?>

 <div class="cta">
  <?php if ( ! empty( $title ) ) {
  echo $args['before_title'] . $title . $args['after_title'];
};
  echo '<a href="' . $link . '">' . $text . '</a>';
  ?>
 </div>

 <?php
 echo $args['after_widget'];

}

Register the Widget

Now you have your class written, it’s time to register the WordPress widget so it works. Add this code outside the class.

//function to register the widget
function kinsta_register_cta_widget() {

 register_widget( 'kinsta_Cta_Widget' );
  
}
add_action( 'widgets_init', 'kinsta_register_cta_widget' );

Now save your plugin file. Go to the Widgets screen and you’ll see the widget for use.

New widget in widgets screen

New widget in widgets screen

If you add it to a widget area and add text and a link to it, it will be output in the live site.

New widget in the live site

New widget in the live site

It might not look all that good right now. You need to add some CSS to style it.

Adding CSS to the Widget

To add CSS to your plugin, you need to create a stylesheet and enqueue it in your plugin. Add this to your plugin file before the class.

function kinsta_widget_enqueue_styles() {

 wp_register_style( 'widget_cta_css', plugins_url( 'css/style.css', __FILE__ ) );
 wp_enqueue_style( 'widget_cta_css' );

}
add_action( 'wp_enqueue_scripts', 'kinsta_widget_enqueue_styles' );

Now you need to add a style.css file inside the plugin’s folder and add any styling to that. I’ll leave that to you!

You now have a simple call to action button that you can add to any widget area on your site. If you add it to your sidebar, for example, people will be able to use it to get to your sign up page from anywhere on the site.

You can create more complex widgets with extra settings and options, but this gives you an idea of how to get started creating your own widget.

If you want to see my code for this plugin, including the styling, you can find it on Github. If you’re starting with code, here’s an in-depth guide on git vs GitHub and how to get started with both.

Widgets are one of the best WordPress features! They can literally change your site from ‘meh’ to ‘yes!’ 🤔😻 Learn what they are, how to use them, and how to code your own widgets with this in-depth guide!Click to Tweet

Summary

Widgets are one of my favorite features of WordPress. They can bring your website to life, and help you get more signups or convert more visitors to customers. You can add WordPress widgets to any existing widget area in your theme, or you can add extra widget areas so that you can add more widgets in more places.

There are also plenty of places to find widgets. WordPress comes with a number of them pre-installed, and you can also install more of them via plugins. But that’s not all, if you feel comfortable, you can also code your own widgets using the Widgets API.

Now it’s your turn: how do you use WordPress widgets on your site? How many are you using?


Get all your applications, databases and WordPress sites online and under one roof. Our feature-packed, high-performance cloud platform includes:

  • Easy setup and management in the MyKinsta dashboard
  • 24/7 expert support
  • The best Google Cloud Platform hardware and network, powered by Kubernetes for maximum scalability
  • An enterprise-level Cloudflare integration for speed and security
  • Global audience reach with up to 35 data centers and 275 PoPs worldwide

Get started with a free trial of our Application Hosting or Database Hosting. Explore our plans or talk to sales to find your best fit.

Понравилась статья? Поделить с друзьями:
  • Как написать виджет для андроид
  • Как написать виджет для windows 10
  • Как написать виджет amocrm
  • Как написать видершпрух
  • Как написать видеоплеер на html