We Offer Free Shipping Worldwide.
Meru Dolls: The Story Behind the Official Meru Collection and a Character Beyond Fantasy
Meru Dolls: The Story Behind the Official Meru Collection and a Character Beyond Fantasy
Explore the journey of Meru the Succubus from a memorable fantasy character to the Official Meru Collection. Learn why fans connect with Meru’s unique design, personality, and the growing world of Meru dolls beyond digital artwork.

Read Now Blog
Who Is Koko? Meet the Goth Girl Behind the Official Darknud Collaboration
Who Is Koko? Meet the Goth Girl Behind the Official Darknud Collaboration
Discover Koko, a unique goth girl character created by Darknud. Learn about her gothic anime style, personality, and the story behind this original character’s journey from digital art to collectible culture.

Read Now Blog
Anime Sex Toys: The Complete Guide to Characters, Materials, and Choosing the Right One
Anime Sex Toys: The Complete Guide to Characters, Materials, and Choosing the Right One
Discover how anime-inspired adult products have evolved through original character design, artist collaborations, and collectible culture. This educational guide covers product categories, materials, fantasy archetypes, maintenance,.

Read Now Blog
Why Meru Became One of the Most Recognizable Succubus Characters Online
Why Meru Became One of the Most Recognizable Succubus Characters Online
Why has Meru remained one of the internet's most recognizable succubus characters? Explore how her unique design, passionate fan community, and official collaborations transformed an original character into a lasting anime icon.

Read Now Blog
Meet the New Meru Butt Sex Toy: A New Chapter in the Official Meru Collection
Meet the New Meru Butt Sex Toy: A New Chapter in the Official Meru Collection
Meet the new Meru Butt Sex Toy at Xhentaidoll. Discover how the latest licensed collaboration expands the Official Meru Collection with premium craftsmanship and authentic character design.

Read Now Blog
What Makes Reiyu GuiGui Different From Other Ghost Girl Characters?
What Makes Reiyu GuiGui Different From Other Ghost Girl Characters?
Explore why Reiyu GuiGui stands apart from traditional ghost girl characters through her elegant design, quiet mystery, and emotional storytelling. Learn how her unique supernatural aesthetic inspired Xhentaidoll's officially licensed collaboration.

Read Now Blog
What Makes Heketa Different From Other Monster Girls?
What Makes Heketa Different From Other Monster Girls?
Not all monster girls leave a lasting impression. This article explores what makes Heketa unique, from her striking visual design and layered personality to the official collaboration that brought her to life.

Read Now Blog
How to Experience Meru: What It Feels Like to Live With a Succubus Companion
How to Experience Meru: What It Feels Like to Live With a Succubus Companion
Meru is a succubus character from Xhentaidoll designed as an immersive fantasy presence beyond traditional design. This article explores her emotional atmosphere and imagination-driven experience.

Read Now Blog
Why Deer Fursonas Feel Different From Wolves, Foxes, and Cats
Why Deer Fursonas Feel Different From Wolves, Foxes, and Cats
Discover what makes deer fursonas unique in the furry fandom. Learn how they compare with wolves, foxes, and cats, why they're loved for their gentle personalities, and how characters like Doe capture the qualities that make original fursonas memorable.

Read Now Blog
Who Is Reiyu GuiGui? Meet the Ghost Girl Between Life and Death
Who Is Reiyu GuiGui? Meet the Ghost Girl Between Life and Death
Meet Reiyu GuiGui, the Ghost Girl VTuber known for her unforgettable personality, unique duality, and loyal Ghostlings community. Discover the story behind the character.

Read Now Blog
Why Heketa Became One of the Most Unique Monster Girls in Anime Fandom
Why Heketa Became One of the Most Unique Monster Girls in Anime Fandom
Heketa isn't a typical monster girl. Beneath her playful appearance lies a dangerous and unpredictable personality that continues to captivate anime fans. Here's why Heketa has become one of the most memorable monster girls in modern fandom.

Read Now Blog
What Makes Meru Different From Other Succubus Characters?
What Makes Meru Different From Other Succubus Characters?
Meru may look like a classic succubus at first glance, but her playful personality, distinctive design, and genuine charm set her apart from typical demon girl characters. Discover what makes Meru different and why fans continue to fall for her.

Read Now Blog
Why Doe Became a Favorite Deer Fursona Among Furry Fans
Why Doe Became a Favorite Deer Fursona Among Furry Fans
Discover what makes Doe a favorite deer fursona among furry fans, from her curious personality to the wholesome charm that defines her character.

Read Now Blog
Why Everyone Falls in Love With Heketa
Why Everyone Falls in Love With Heketa
Discover the story behind Heketa, one of DiivesArt's most beloved monster girls. Explore her origins, personality, Xingzuo Temple lore, and why fans are drawn to her unique blend of beauty, loneliness, and mystery.

Read Now Blog
Who Is Meru? Meet the Succubus Who Never Plays Fair
Who Is Meru? Meet the Succubus Who Never Plays Fair
Meet Meru, the playful succubus who never plays fair. Discover her personality, story, and the charm that has made her one of Xhentaidoll's most beloved demon girl characters.

Read Now Blog
Who Is Doe? The Story Behind Our Deer Fursona
Who Is Doe? The Story Behind Our Deer Fursona
Discover the story behind Doe, the beloved deer fursona inspired by curiosity, grace, and creativity. Learn what makes this furry deer character unique and why fans connect with her.

Read Now Blog
How to Have a Prostate Orgasm: A Beginner-Friendly Guide to P-Spot Pleasure
How to Have a Prostate Orgasm: A Beginner-Friendly Guide to P-Spot Pleasure
Learn how to have a prostate orgasm with this beginner's guide to prostate massage, male G-spot stimulation, P-spot pleasure, safety tips, and practical techniques for a more enjoyable experience.

Read Now Blog
Who Is Doe? The Story Behind Xhentaidoll's Most Popular Deer Fursona
Who Is Doe? The Story Behind Xhentaidoll's Most Popular Deer Fursona
Who is Doe? Discover the story behind Xhentaidoll's iconic deer fursona, inspired by artist @alfa995. From digital artwork to a beloved fantasy character, explore how Doe became a symbol of creativity, curiosity, and immersive furry culture.

Read Now Blog
How to Learn Rope Bondage Alone: A Beginner’s Guide to Safe Knots, Common Mistakes & Solo Practice
How to Learn Rope Bondage Alone: A Beginner’s Guide to Safe Knots, Common Mistakes & Solo Practice
Beginner rope bondage guide: learn rope bondage alone with safety tips, essential knots, and solo practice methods. Perfect for safe, hands-on beginner training before involving a partner.

Read Now Blog
So… What Even Is a Footjob? (And Why Reddit Talks About It So Much)
So… What Even Is a Footjob? (And Why Reddit Talks About It So Much)
A casual, Reddit-inspired guide to foot play, furry paw fantasies, and internet kink culture. This beginner-friendly blog explores why people enjoy foot-related fantasies, why first experiences are often awkward.

Read Now Blog
click load more
const TAG = "spz-custom-popup"; const DISPLAY_TYPE = { POPUP: "PTT_POPUP" // 弹窗 }; const API = { LIST: `/api/storefront/promotion/placement/list`, // 获取弹窗列表 REPORT: `/api/storefront/promotion/placement/data/report` // 上报数据 }; const DISPLAY_DEVICE = { PC_AND_MOBILE: "PD_PC_MOBILE", // PC和移动端 PC: "PD_PC", // PC MOBILE: "PD_MOBILE" // 移动端 }; const REPORT_EVENT = { CLICK: "PE_CLICK", // 点击事件 IMPRESSION: "PE_IMPRESSION" // 曝光事件 }; class SpzCustomPopup extends SPZ.BaseElement { constructor(element) { super(element); this.popupList_ = []; // 弹窗数据 this.popupZIndex = 1050; // 弹窗层级 // 节流处理 每5s内多次点击 算一次点击上报 this.throttleReport = this.win.SPZCore.Types.throttle( this.win, (data) => { this.reportData(data) }, 5000 ) } static deferredMount() { return false; } buildCallback() { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); this.setupAction_(); this.viewport_ = this.getViewport(); } mountCallback() { this.fetchData_(); } // 接口请求,获取数据 fetchData_() { const id = window.SHOPLAZZA.meta.page.template_type === 51 ? window.SHOPLAZZA.meta.page.resource_id : 0; return this.xhr_.fetchJson(API.LIST, { method: 'POST', body: { page_id: window.SHOPLAZZA.meta.page.template_type, placement_type: DISPLAY_TYPE.POPUP, discount_id: id } }).then((res) => { // 请求成功 执行render this.doRender_(res.list); }).catch((err) => { console.error(err); }); } // 渲染dom doRender_(data) { this.popupList_ = data || []; if (this.popupList_.length > 0) { this.popupList_.forEach((item) => { item.config = JSON.parse(item.config); }) } return this.templates_ .findAndRenderTemplate(this.element, { list: this.popupList_ }) .then((el) => { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); this.element.appendChild(el); }) .then(() => { // 遍历显示弹窗 this.popupList_.forEach((item) => { this.showPopup_(item); }); }) } showPopup_(popup) { // 展示弹窗 符合展示条件的弹窗 const $popup = document.querySelector(`#popup-${popup.id}`); $popup && SPZ.whenApiDefined($popup).then((api)=> { const isPC = this.viewport_.getWidth() >= 960; const isMobile = this.viewport_.getWidth() < 960; const isMatchPCDevice = popup.device === DISPLAY_DEVICE.PC_AND_MOBILE || popup.device === DISPLAY_DEVICE.PC; const isMatchMobileDevice = popup.device == DISPLAY_DEVICE.PC_AND_MOBILE || popup.device === DISPLAY_DEVICE.MOBILE; if((isPC && isMatchPCDevice) || (isMobile && isMatchMobileDevice)) { // 根据推送时间 延迟展示弹窗 setTimeout(() => { api.open(); }, popup.delay_seconds * 1000); } }) } // 上报数据 async reportData(data) { this.xhr_.fetchJson(API.REPORT, { method: "POST", body: { placement_id: data.placement_id, event: data.event } }); } setupAction_() { this.registerAction('handleTrack', async(invocation) => { // 如果是主题编辑器则不用处理 if(window.top !== window.self) { return; } const data = invocation.args; const event = data.event; // 点击上报 节流处理 if(event === REPORT_EVENT.CLICK) { await this.throttleReport(data); } else { this.reportData(data); } }); } triggerEvent_(name, data) { const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {}); this.action_.trigger(this.element, name, event); } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement(TAG, SpzCustomPopup);
const TAG = "spz-custom-announcement"; const DISPLAY_TYPE = { ANNOUNCEMENT: "PTT_BANNER" // 公告栏 }; const API = { LIST: `/api/storefront/promotion/placement/list`, // 获取公告栏列表 REPORT: `/api/storefront/promotion/placement/data/report` // 上报数据 }; const DISPLAY_DEVICE = { PC_AND_MOBILE: "PD_PC_MOBILE", // PC和移动端 PC: "PD_PC", // PC MOBILE: "PD_MOBILE" // 移动端 }; const REPORT_EVENT = { CLICK: "PE_CLICK", // 点击事件 IMPRESSION: "PE_IMPRESSION" // 曝光事件 }; const POSITION = { TOP: "PP_TOP", // 顶部 BOTTOM: "PP_BOTTOM" // 底部 } const MODE = { FIXED: "PM_FIXED", // 固定 NORMAL: "PM_SCROLLING" // 滚动 } const THEME_NAME = window.SHOPLAZZA.theme.merchant_theme_name; class SpzCustomAnnouncement extends SPZ.BaseElement { constructor(element) { super(element); this.announcementList_ = []; // 公告栏数据 } static deferredMount() { return false; } buildCallback() { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); this.setupAction_(); this.viewport_ = this.getViewport(); } mountCallback() { this.fetchData_(); this.createAnnouncementDom_(); this.listenCartChange_(); } fetchData_(type = '') { const id = window.SHOPLAZZA.meta.page.template_type === 51 ? window.SHOPLAZZA.meta.page.resource_id : 0; return this.xhr_.fetchJson(API.LIST, { method: 'POST', body: { page_id: window.SHOPLAZZA.meta.page.template_type, placement_type: DISPLAY_TYPE.ANNOUNCEMENT, discount_id: id } }).then((res) => { this.announcementList_ = res.list || []; if (this.announcementList_.length > 0) { this.announcementList_.forEach((item) => { item.config = JSON.parse(item.config); }); } if(type === 'cartChange') { this.announcementList_.forEach((item) => { this.updateText_(item); }); } else { this.doRender_(this.announcementList_); } }).catch((error) => { console.error(error); }) } doRender_(data) { return this.templates_ .findAndRenderTemplate(this.element, { list: this.announcementList_ }) .then((el) => { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); this.element.appendChild(el); }) .then(() => { this.announcementList_.forEach((item) => { this.showAnnouncement_(item); }); }).then(() => { this.handleThemeCompatibility_(); }); } // 更新文案 updateText_(item) { const announcement = document.querySelector(`#announcement-${item.id}`); const announcementText = announcement.querySelectorAll('.announcement_text'); const textArr = item.config.text_discount.replace_texts; const textDom = textArr.map((text) => { return `${text}`; }).join(','); announcementText.forEach((text) => { text.innerHTML = textDom; }); } // 创建公告栏dom createAnnouncementDom_() { const isHero = /Hero/.test(THEME_NAME); const isEva = /Eva/.test(THEME_NAME); const headerEl = document.querySelector('[data-section-type="header"]'); const headerSticky = headerEl && SPZCore.Dom.computedStyle(this.win, headerEl).position === 'sticky'; // 创建滚动的底部公告栏 const announcementBottomContainer = document.createElement('div'); announcementBottomContainer.className = 'announcement__container_bottom bootstrap'; document.body.appendChild(announcementBottomContainer); // 创建固定的底部公告栏 const announcementBottomSticky = document.createElement('ljs-sticky'); announcementBottomSticky.className = 'announcement__container_bottom-sticky'; announcementBottomSticky.setAttribute('layout', 'container'); announcementBottomSticky.setAttribute('position', 'bottom'); announcementBottomSticky.style.position = 'fixed'; announcementBottomSticky.style.bottom = '0'; announcementBottomSticky.style.left = '0'; announcementBottomSticky.style.right = '0'; announcementBottomSticky.style.zIndex = '1030'; document.body.appendChild(announcementBottomSticky); const announcementTopContainer = document.createElement('div'); announcementTopContainer.classList.add('announcement__container_top'); if (isHero) { announcementTopContainer.classList.add('announcement__container_top_zIndex_1030'); } announcementTopContainer.classList.add('bootstrap'); document.body.insertBefore(announcementTopContainer, document.body.children[0]); const announcementTopFixedContainer = document.createElement('div'); announcementTopFixedContainer.classList.add('announcement__container_top-fixed'); if (isHero) { announcementTopFixedContainer.classList.add('announcement__container_top_zIndex_1030'); } announcementTopFixedContainer.classList.add('bootstrap'); const insertBeforeElement = headerSticky ? headerEl : document.body; insertBeforeElement.insertBefore(announcementTopFixedContainer, insertBeforeElement.children[0]); if (isEva) { const evaHeader = document.querySelector('header.header'); const isEvaMaskHeader = evaHeader && SPZCore.Dom.computedStyle(this.win, evaHeader).position === 'absolute'; let fixedBannerTopContainer = document.querySelector('.announcement__container_top-fixed'); if (isEvaMaskHeader) { if (fixedBannerTopContainer) { fixedBannerTopContainer.remove(); } const newBanner = document.createElement('div'); newBanner.className = 'announcement__container_top-fixed bootstrap'; document.body.insertBefore(newBanner, document.body.firstChild); fixedBannerTopContainer = newBanner; } else { if (!headerEl) return; const observer = new MutationObserver(() => { const isSticky = SPZCore.Dom.computedStyle(this.win, headerEl).position === 'sticky'; if (!isSticky) return; const isTopFixedAnnouncementInHeader = headerEl.querySelector('.announcement__container_top-fixed'); if (isTopFixedAnnouncementInHeader) return; const announcementTopFixedContainer = document.querySelector('.announcement__container_top-fixed'); if (announcementTopFixedContainer) { announcementTopFixedContainer.remove(); headerEl.insertBefore(announcementTopFixedContainer, headerEl.children[0]); observer.disconnect(); } }); observer.observe(headerEl, { attributes: true, attributeFilter: ['style', 'class'] }); } if (headerSticky && !isEvaMaskHeader && fixedBannerTopContainer) { fixedBannerTopContainer.style.position = 'relative'; fixedBannerTopContainer.style.zIndex = '29'; } } } // 展示公告栏 showAnnouncement_(item) { const announcement = document.querySelector(`#announcement-${item.id}`); const announcementBottomContainer = document.querySelector('.announcement__container_bottom'); const announcementBottomSticky = document.querySelector('.announcement__container_bottom-sticky'); const announcementTopContainer = document.querySelector('.announcement__container_top'); const announcementTopFixedContainer = document.querySelector('.announcement__container_top-fixed'); const isPC = this.viewport_.getWidth() >= 960; const isMobile = this.viewport_.getWidth() < 960; const isMatchPCDevice = item.device === DISPLAY_DEVICE.PC_AND_MOBILE || item.device === DISPLAY_DEVICE.PC; const isMatchMobileDevice = item.device == DISPLAY_DEVICE.PC_AND_MOBILE || item.device === DISPLAY_DEVICE.MOBILE; if((isPC && isMatchPCDevice) || (isMobile && isMatchMobileDevice)) { if (item.position === POSITION.BOTTOM) { if(item.mode === MODE.FIXED) { announcementBottomSticky && announcementBottomSticky.appendChild(announcement); } else { announcementBottomContainer && announcementBottomContainer.appendChild(announcement); } } else { if (item.mode === MODE.FIXED) { announcementTopFixedContainer && announcementTopFixedContainer.appendChild(announcement); } else { announcementTopContainer && announcementTopContainer.appendChild(announcement); } } this.reportData({ placement_id: item.id, event: REPORT_EVENT.IMPRESSION }); } } // 处理主题兼容 handleThemeCompatibility_() { try { const isBoost = /Boost/.test(THEME_NAME); const isHyde = /Hyde/.test(THEME_NAME); const isEva = /Eva/.test(THEME_NAME); const boostHeader = document.querySelector('.boost-header'); const fixedBannerTopContainer = document.querySelector('.announcement__container_top-fixed'); const notFixedBannerTopContainer = document.querySelector('.announcement__container_top'); const headerEl = document.querySelector('[data-section-type="header"]'); const headerSticky = headerEl && SPZCore.Dom.computedStyle(this.win, headerEl).position === 'sticky'; const header = document.querySelector('.header__fixed') || document.querySelector('.header__wrapper'); const headerFixed = header && SPZCore.Dom.computedStyle(this.win, header).position === 'fixed'; const handleScroll = SPZCore.Types.throttle(this.win, () => { if (isHyde) { if (header && headerSticky) { header.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`; } else { notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`; } } if (isEva) { const evaHeader = document.querySelector('header.header'); const isEvaMaskHeader = evaHeader && SPZCore.Dom.computedStyle(this.win, evaHeader).position === 'absolute'; if (!isEvaMaskHeader) return; if (evaHeader.classList.contains('header__fixed')) { evaHeader.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`; } else { notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`; } if(document.documentElement.scrollTop === 0) { evaHeader.style.marginTop = '0'; } } if (headerSticky) return; if (headerFixed) { header.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`; } else { const observer = new MutationObserver((mutationsList, observer) => { for (const mutation of mutationsList) { if (mutation.type === 'childList' && fixedBannerTopContainer.childElementCount > 0) { notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`; observer.disconnect(); // 停止观察 break; } } }); // 开始观察 fixedBannerTopContainer 的子节点变化 observer.observe(fixedBannerTopContainer, { childList: true, subtree: true }); // 初始检查 if (fixedBannerTopContainer.childElementCount > 0) { notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`; } if(header) { header.style.marginTop = '0'; } } if (isBoost) { fixedBannerTopContainer.style.zIndex = '1031'; if (boostHeader && boostHeader.classList.contains('header__fixed')) { boostHeader.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`; } else { notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`; } } }, 16); window.addEventListener('scroll', handleScroll); window.dispatchEvent(new Event('scroll')); } catch (error) { console.error('error', error); } } // 上报数据 async reportData(data) { // 如果是主题编辑器则不用处理 if(window.top !== window.self) { return; } this.xhr_.fetchJson(API.REPORT, { method: "POST", body: { placement_id: data.placement_id, event: data.event } }); } // 监听购物车变化事件dj.cartChange listenCartChange_() { SPZUtils.Event.listen(document, 'dj.cartChange', (event) => { this.fetchData_('cartChange'); }); } setupAction_() { this.registerAction('handleClose', (invocation) => { const data = invocation.args; const id = data.id; const announcement = document.querySelector(`#announcement-${id}`); announcement && SPZCore.Dom.removeElement(announcement); window.dispatchEvent(new Event('scroll')); }); this.registerAction('handleJumpLink', (invocation) => { const data = invocation.args; if(!data.show_url) return; data.url && window.open(data.url, data.open_new_window ? '_blank' : '_self'); this.reportData({ placement_id: data.id, event: REPORT_EVENT.CLICK }); }); } triggerEvent_(name, data) { const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {}); this.action_.trigger(this.element, name, event); } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement(TAG, SpzCustomAnnouncement);