Update v3.7.0 This version brings major improvements to Monetization (SafeLink) and SEO (Titles), along with core stability fixes for PWA and Ads.
Important!
Before making any changes to your theme XML or settings, please backup your theme. Go to Theme > Backup > Download to save a copy of your current version.
Table of Contents

Welcome everyone! We are excited to announce the release of Plus UI v3.7.0. This update focuses on maximizing your revenue through advanced SafeLink features and improving your blog's search engine visibility.
1. Custom Home Page Title (SEO)
Previously, the home page title relied on the blog name. Now, you can set a separate, SEO-optimized title specifically for the home page.
- Open your Blogger Theme XML editor and search for the following variable:
<Variable name="home.title" description="Enter Your Custom Title in Value (Enable Custom Title Plugin)" type="string" default="" value="Plus Ui"/> [!] Enter Your Custom Home page Title in Value [!] @type {String} [!] Page: its Only For Home Page [!] Note: Must Should enable Custom Home page Title Plugin To use this Title - Replace the
value(currently "Plus Ui") with your desired SEO Title. -
Activate the Plugin: Go to Blogger > Theme Designer > Advanced.
- Find Plugin: Custom Home Page Title.
- Change the value from 1px to 2px.
Done! Your custom home page title is now successfully set up.
2. Multi-page SafeLink (Advanced)
We have overhauled the SafeLink system. You can now choose between the classic Single Page mode or the new Multi-Page mode which supports automatic page picking and is compatible with Adslinkfly.
2.1 Multi-page SafeLink (New)
This mode automatically picks pages from your blog feed and supports multiple steps, making it ideal for increasing ad impressions.
- Features: Multi-pages, Multiple steps, Auto + Manual page picking, Supports Manual posts, Supports Adslinkfly.
- How to Enable: Go to Theme Designer > Advanced > Plugin: Safelink.
- Set the length to 3px.
2.2 Single Page SafeLink (Old)
The classic one-step safelink method.
- Features: Single page, One step, Manual pages only.
- Adslinkfly Support: No.
- How to Enable: Go to Theme Designer > Advanced > Plugin: Safelink.
- Set the length to 2px.
2.3 SafeLink Options Explained
Customize the behavior of your SafeLink system using the sliders in Theme Designer > Advanced. Refer to the table below for details on each option.
|
| Figure: Enable "Multi Pages" by setting the slider to 3px. |
| Option Name | Values | Description |
|---|---|---|
| Safelink Button Behavior | 1 = Always Show 2 = Click to Scroll |
(1) Buttons are visible immediately. (2) User must click a trigger or scroll to reveal the button. |
| Auto Encrypt Manual Links | 1 = Disable 2 = Enable |
Automatically encrypts external links found in your posts (with class .safeL) into safelinks. |
| Open Encrypted Link in New Tab | 1 = Disable 2 = Enable |
When a user clicks a safelink, it opens the decryption page in a new browser tab. |
| Open Destination Link in New Tab | 1 = Disable 2 = Enable |
Once the timer finishes, the final destination URL opens in a new tab. |
| Safelink Countdown Seconds | Time (e.g., 14) | Sets the duration (in seconds) the user must wait before the link is ready. |
| Total Steps for Safelink | Number (e.g., 4) | (Multi-page mode only) Sets how many pages/clicks the user must go through. |
| Safelink AutoScroll | 1 = Disable 2 = Enable |
Automatically scrolls the user's screen to the timer or button location. |
2.4 Custom Placement (Advanced)
By default, the SafeLink controls (Timers and "Next" buttons) automatically appear at the very top and bottom of your post content (.post .pInr). However, you can manually force them to appear exactly where you want.
Manual Placement:
Add the following specific IDs to any <div> in your Post or Theme Layout to override the default position:
id="sl_top_section": The container for the top element (e.g., Timer or Ads).id="sl_bottom_section": The container for the bottom element (e.g., "Next" Button).
<!-- Example: Custom placement inside a post -->
<p>Some intro text...</p>
<!-- The timer/ad will appear here -->
<div id='sl_top_section'></div>
<p>Main article content...</p>
<!-- The Next button will appear here -->
<div id='sl_bottom_section'></div>
Note: If these IDs are not found, the script automatically looks for the post content container or standard ad sections (sec_Horizontal-Ad) to place the elements.
Configure SafeLink Pages
To use this feature, you must define the pages in your HTML.
- Go to Blogger HTML Editor.
- Find the following code snippet and input your page paths. You must add at least one page.
Warning!
Only put the pathname of the page (e.g., /p/my-page.html), not the full URL.
<Variable name="safelink.page1" description="Safelink Page 1" type="string" default="" value="/p/safelink-page-1.html"/>
[!] Safelink Page 1
[!] @type {String}
[!] Warning: Don't add full url of the safelink page, only include the pathname
<Variable name="safelink.page2" description="Safelink Page 2" type="string" default="" value=""/>
[!] Safelink Page 2
[!] @type {String}
[!] Warning: Don't add full url of the safelink page, only include the pathname
<Variable name="safelink.page3" description="Safelink Page 3" type="string" default="" value=""/>
[!] Safelink Page 3
[!] @type {String}
[!] Warning: Don't add full url of the safelink page, only include the pathname
<Variable name="safelink.page4" description="Safelink Page 4" type="string" default="" value=""/>
[!] Safelink Page 4
[!] @type {String}
[!] Warning: Don't add full url of the safelink page, only include the pathname
Safelink Generator Tool
You can embed this generator tool on your site to create safelinks easily.
- Create a new Page or Post and switch to HTML View.
- Copy and paste the code below:
<!--[ Begin: Safelink Generator area ]-->
<style>
.inF.cB button{--svgW:16px;--svgH:16px;position:absolute;inset-block-start:10px;inset-inline-end:10px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;background:var(--contentB);border-radius:8px;border:1px solid var(--contentLa);opacity:0.5;cursor:pointer}
.inF.cB input{padding-inline-end:50px}
.inF.cB input:not(:placeholder-shown) ~ button{opacity:1}
.sgMw{max-width:600px;margin:40px auto}
.sgOw{display:flex;align-items:center;gap:12px 8px;flex-wrap:wrap;background:var(--contentB);border:1px solid var(--contentL);border-radius:5px;padding:12px}
.sgOw span{width:100%;line-height:1.4em;font-size:14px}
.sgOw button{--svgW:20px;--svgH:20px;display:flex;align-items:center;justify-content:center;flex-shrink:0;width:36px;height:36px;background:var(--linkB);color:#fffdfc;border-radius:8px;cursor:pointer}
</style>
<script>
/*! Plus UI Javascript (safelink/generator.js) | Authors: Deo Kumar, Armaan Kumar (https://fineshopdesign.com) | License: Unlicensed | Copyright (c) 2024-2025 Fineshop Design */
"use strict";((e,t,l)=>{let{cEl:n,iAE:a,aEL:s,qSel:i,gId:p,eHTML:o,tNtf:g,df:c,pl:u,bg:r}=e,d=e=>(e=>new URL(e,l.baseURI))((e=>e.replace(/(^\w+:|^)/,""))(e)),h=(t,l,n="s")=>{let a=(t=>{let l=JSON.stringify(t);return{decoded:t,value:l,data:e.B64.O3.e(l)}})(l);return t+`#${n}=${encodeURIComponent(a.data)}`},v=u.sl,b=v.pg.map(e=>new URL(e,r.cnHmU).href),f=l.currentScript,C=[];v.ok||C.push("The Safelink plugin is not enabled. The generated links will not work until it is enabled."),0===b.length&&C.push("No Safelink page has been configured!");let k=n("div",{className:"sgMw",innerHTML:`${0!==C.length?`<div class='alert warning'><b>Warning!</b>${C.map((e,t)=>`${t+1}. ${e}`).join("<br>")}</div>`:""}<div class='inF cB' data-message='URL must begin with http:// or https://'><input type='text' name='link' id='sg_f_link' placeholder=' '><label for='sg_f_link'>Destination URL</label><button type='button' id='sg_f_clear_link'><svg class='line' viewBox='0 0 24 24'><path d='M19.0005 4.99988L5.00049 18.9999M5.00049 4.99988L19.0005 18.9999'></path></svg></button></div><div class='inF' data-message='Select a page for safelink'><select id='sg_f_page'><optgroup label='Static pages'><option value='${o(r.cnHmU)}'${0===b.length?" selected":""}>Homepage</option></optgroup>${!v.ver&&0!==b.length?`<optgroup label='Safelink Pages'>${b.reduce((e,t,l)=>`${e}<option value='${o(t)}'${0===l?" selected":""}>Safelink Page (${o(v.pg[l])})</option>`,"")}</optgroup>`:""}</select><label for='sg_f_page'>Safelink Page</label></div><div class='sgOw'><span class='sgOl'></span><button type='button' class='sgOv'><svg class='line' viewBox='0 0 24 24'><path d='M15.58 12C15.58 13.98 13.98 15.58 12 15.58C10.02 15.58 8.42004 13.98 8.42004 12C8.42004 10.02 10.02 8.42004 12 8.42004C13.98 8.42004 15.58 10.02 15.58 12Z'></path><path d='M12 20.27C15.53 20.27 18.82 18.19 21.11 14.59C22.01 13.18 22.01 10.81 21.11 9.39997C18.82 5.79997 15.53 3.71997 12 3.71997C8.46997 3.71997 5.17997 5.79997 2.88997 9.39997C1.98997 10.81 1.98997 13.18 2.88997 14.59C5.17997 18.19 8.46997 20.27 12 20.27Z'></path></svg></button><button type='button' class='sgOc'><svg class='line' viewBox='0 0 24 24'><path d='M16 12.9V17.1C16 20.6 14.6 22 11.1 22H6.9C3.4 22 2 20.6 2 17.1V12.9C2 9.4 3.4 8 6.9 8H11.1C14.6 8 16 9.4 16 12.9Z'></path><path d='M22 6.9V11.1C22 14.6 20.6 16 17.1 16H16V12.9C16 9.4 14.6 8 11.1 8H8V6.9C8 3.4 9.4 2 12.9 2H17.1C20.6 2 22 3.4 22 6.9Z'></path></svg></button></div>`});a(f,"beforebegin",k);let $=p("sg_f_link"),_=p("sg_f_clear_link"),m=p("sg_f_page"),w=i(".sgOl",k),H=i(".sgOv",k),L=i(".sgOc",k),U=()=>{if(!e.B64)return null;let t=$.value.trim();return""===t?null:(/^https?:\/\//.test(t)||(t=`https://${t}`),h(m.value,{v:1,u:t}))},M=()=>{let e=U();w.innerText=e||"Input a valid Destination URL first!"};M(),s($,"change",M),s($,"input",M),s($,"keyup",M),s(m,"change",M),s(m,"input",M),s($,"blur",()=>{let e=$.value.trim();""!==e&&(/^https?:\/\//.test(e)?$.value!==e&&($.value=e):$.value=`https://${e}`)}),s(_,"click",()=>{$.value="",M()}),s(H,"click",()=>{let e=U();e?t.open(e,"_blank"):g(w.textContent)}),s(L,"click",()=>{let t=U();t?e.cpT(t).then(()=>g("Link copied to clipboard!")):g(w.textContent)}),c.then(()=>{M();if(v.ver){return;}e.iBF().then(async e=>{let t=new e(d(r.cnHmU)),[l,a]=await Promise.all([t.posts.list(),t.pages.list()]);[["Recent Posts",l],["Recent Pages",a]].forEach(([e,t])=>{let l=n("optgroup",{attributes:{label:e},innerHTML:t.reduce((e,t)=>`${e}<option value='${o(t.url)}'>${o(t.title)}</option>`,"")});m.appendChild(l)})})})})(PU,window,document);
</script>
<!--[ End: Safelink Generator area ]-->
3. Bug Fixes: Middle Post Ads
In version 3.2.0, some users reported issues with ads not rendering correctly in the middle of posts. We have upgraded the middle ads script in v3.7.0, and it is now working 100% effectively.
4. PWA Stability Improvements
We have significantly improved the stability of the Progressive Web App (PWA) functionality. Previous issues where the "Install App" prompt would not appear on certain Android versions have been resolved.
How to test the new PWA:
- Clear your browser cache.
- Visit your blog on a mobile device (Chrome or Safari).
- You should see the "Add to Home Screen" or "Install App" prompt appear faster and more reliably.
- The app now functions smoothly offline for cached pages.
5. Core Updates: Adslinkfly & Status Code
Two major core updates have been applied to improve functionality.
5.1 Adslinkfly Script Update
Update your view_banner.ctp with the code below to ensure compatibility with the new Safelink system.
<?php
$lurl = "safelink.page.gd";
$burl = "plus-ul.blogspot.com";
/** Custom Base64 encoder */
function custom_base64_encode($string) {
$dict = "MNBVCXZLKJHGFDSAPOIUYTREWQmnbvcxzlkjhgfdsapoiuytrewq0987654321+/=";
$std = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
$b64 = base64_encode($string);
return strtr($b64, $std, $dict);
}
/** Referrer check */
$ref = $_SERVER['HTTP_REFERER'] ?? '';
$do = parse_url($ref);
$refer = $do['host'] ?? '';
if ($refer != $burl) {
$originalLink = 'https://' . $lurl . '/' . urlencode($link->alias);
// Create JSON object for safelink
$jsonLink = json_encode([
"v" => 1, // version or flag
"u" => $originalLink
]);
// Encode JSON with custom Base64
$encodedLink = custom_base64_encode($jsonLink);
// Final redirect URL
$finalUrl = 'https://' . $burl . '/#?url=' . $encodedLink;
header("Location: $finalUrl", true, 307);
exit();
}
?>
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Link $link
* @var \App\Model\Entity\Post $post
* @var mixed $ad_form_data
* @var string $banner_336x280
* @var string $banner_468x60
* @var string $banner_728x90
* @var mixed $pop_ad
* @var mixed $show_pop_ad
* @var \App\Model\Entity\Plan $link_user_plan
*/
$this->assign('title', get_option('site_name'));
$this->assign('description', get_option('description'));
$this->assign('content_title', get_option('site_name'));
$this->assign('og_title', $link->title);
$this->assign('og_description', $link->description);
$this->assign('og_image', $link->image);
?>
<?php $this->start('scriptTop'); ?>
<script type="text/javascript">
if (window.self !== window.top) {
window.top.location.href = window.location.href;
}
</script>
<?php $this->end(); ?>
<div class="box-main">
<?php if (!empty($banner_728x90)) : ?>
<div class="banner banner-728x90">
<div class="banner-inner">
<?= $banner_728x90; ?>
</div>
</div>
<?php endif; ?>
<?php if ($post): ?>
<div class="blog-item">
<div class="page-header">
<h3>
<small><a href="<?= build_main_domain_url('/blog') ?>"><?= __('From Our Blog') ?>:</a>
</small> <?= h($post->title) ?></h3>
</div>
<div class="blog-content"><?= $post->description ?></div>
</div>
<?php endif; ?>
<h4><?= __('Your link is almost ready.') ?></h4>
<span id="countdown" class="countdown">
<span id="timer" class="timer">
<?= $link_user_plan->timer ?? 5 ?>
</span><br><?= __('Seconds') ?>
</span>
<?php if (!empty($banner_468x60)) : ?>
<div class="banner banner-468x60">
<div class="banner-inner">
<?= $banner_468x60; ?>
</div>
</div>
<?php endif; ?>
<?php
$hidden_class = '';
if (empty($link->image) && empty($link->title) && empty($link->description)) {
$hidden_class = 'hidden';
}
?>
<?php if (get_option('short_link_content', 'no') === 'yes') : ?>
<div class="link-details <?= $hidden_class ?>">
<div class="panel panel-default">
<div class="panel-body">
<img class="link-image" src="<?= h($link->image) ?>"/>
<h4 class="link-title"><?= h($link->title) ?></h4>
<p class="link-description"><?= h($link->description) ?></p>
</div>
</div>
</div>
<?php endif; ?>
<div style="margin-bottom: 10px;">
<a href="javascript: void(0)" class="btn btn-success btn-lg get-link disabled">
<?= __('Please wait...') ?>
</a>
</div>
<?php if (!empty($banner_336x280)) : ?>
<div class="banner banner-336x280">
<div class="banner-inner">
<?= $banner_336x280; ?>
</div>
</div>
<?php endif; ?>
</div>
<?=
$this->Form->create(null, [
'url' => ['controller' => 'Links', 'action' => 'go', 'prefix' => false],
'id' => 'go-link',
'class' => 'hidden',
]);
?>
<?= $this->Form->hidden('ad_form_data', ['value' => $ad_form_data]); ?>
<?=
$this->Form->button(__('Submit'), [
'id' => 'go-submit',
'class' => 'hidden',
]);
?>
<?= $this->Form->end(); ?>
<?php if (get_option('enable_popup', 'yes') == 'yes' && $show_pop_ad) : ?>
<?=
$this->Form->create(null, [
'url' => ['controller' => 'Links', 'action' => 'popad', 'prefix' => false],
'target' => "_blank",
'id' => 'go-popup',
'class' => 'hidden',
]);
?>
<?= $this->Form->hidden('pop_ad', ['value' => $pop_ad]); ?>
<?= $this->Form->end(); ?>
<?php endif; ?>
<?php $this->start('scriptBottom'); ?>
<?php $this->end(); ?>
-
First, locate the line:
$lurl = "safelink.page.gd";
Replace safelink.page.gd with your own Safelink domain. -
Next, find the line:
$burl = "plus-ul.blogspot.com";
Replace plus-ul.blogspot.com with your own Blogspot domain. - Compatibility: This Adslinkfly script works only with the Plus UI theme.
5.2 Blog Status Code (Last Month Views)
You can now display a visual chart of your blog's estimated views for the last month. Place the following code where you want the chart to appear.
<!--[ Last month estimated views chart ]-->
<script>
"use strict";!((a,b,c)=>{if(!navigator.onLine)return;const d=c.currentScript,e=d.insertAdjacentElement("beforebegin",a.cEl("canvas",{style:"width: 100%; height: auto;",width:800,height:400,ariaLabel:"Estimated views chart",role:"img"}));a.lz.then(()=>a.df).then(()=>a.lJs("https://cdn.jsdelivr.net/npm/chart.js")).then(()=>{const b=new URL(a.cf.bst.su,a.bg.cnHmU);return b.searchParams.set("timeRange","LAST_MONTH"),fetch(b).then(a=>a.ok?a.json():null)}).then(b=>{if(!b)return;const{rows:c}=(a=>{const b=a.total,c=a.sparklineData,d=c.reduce((a,[,b])=>a+b,0),e=[],f=new Date;for(const[g,h]of c){const a=new Date(Date.UTC(f.getUTCFullYear(),f.getUTCMonth(),f.getUTCDate()-(29-g))),c=a.toLocaleDateString("en-GB",{day:"2-digit",month:"short"}),i=Math.round(h/d*b);e.push({date:c,views:i})}return{total:b,rows:e,sparks:c}})(b),d=e.getContext("2d"),f=d.createLinearGradient(0,0,0,e.height);f.addColorStop(0,"rgba(195, 113, 239, 0.15)"),f.addColorStop(1,"rgba(0, 0, 0, 0)"),new Chart(e,{type:"line",data:{labels:c.map(a=>a.date),datasets:[{label:"Estimated Views",data:c.map(a=>a.views),fill:!0,tension:.4,borderColor:"#c371ef",borderWidth:2,backgroundColor:f,pointRadius:2,pointHoverRadius:5,pointHoverBorderWidth:4,pointHoverBackgroundColor:"#fff"}]},options:{responsive:!0,interaction:{mode:"index",intersect:!1},plugins:{tooltip:{backgroundColor:"rgba(53, 27, 92, 0.8)",caretPadding:5,boxWidth:5,usePointStyle:"triangle",boxPadding:3,callbacks:{label:a=>`Views: ${a.raw}`,title:a=>`Date: ${a[0].label}`}},legend:{display:!1,labels:{usePointStyle:!0}}},scales:{x:{grid:{display:!1},title:{display:!1,text:"Date"}},y:{title:{display:!1,text:"Views"},beginAtZero:!0,ticks:{callback:b=>a.abvN(b,2).join("")}}}}})})})(PU,window,document);
</script>
Live Demo
Want to see the new Multi-page SafeLink and Status Chart in action?
Conclusion
The Plus UI v3.7.0 update represents a significant step forward in giving you control over your site's monetization and SEO. We highly recommend upgrading to take advantage of the new Safelink capabilities and bug fixes. Thank you for your continued support!