Halloween BOO Door Curtain, Pumpkin Spider Web Porch Banner, Spooky Front Door Cover, Outdoor Halloween Decoration, Jack O Lantern Hanging Banner, Fall Entryway Decor

$29.99 $40.99 Save $11.00
/** * 优惠码组件模型类 * 处理优惠码的显示和交互逻辑 */ class SpzCustomDiscountCodeModel extends SPZ.BaseElement { constructor(element) { super(element); // 复制按钮和内容的类名 this.copyBtnClass = "discount_code_btn" this.copyClass = "discount_code_value" } isLayoutSupported(layout) { return layout == SPZCore.Layout.LOGIC; } buildCallback() { // 初始化服务 this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); } /** * 渲染优惠码组件 * @param {Object} data - 渲染数据 */ doRender_(data) { return this.templates_ .findAndRenderTemplate(this.element, Object.assign(this.getDefaultData(), data) ) .then((el) => { this.clearDom(); this.element.appendChild(el); // 绑定复制代码功能 this.copyCode(el, data); }); } /** * 获取渲染模板 * @param {Object} data - 渲染数据 */ getRenderTemplate(data) { const renderData = Object.assign(this.getDefaultData(), data); return this.templates_ .findAndRenderTemplate(this.element, renderData) .then((el) => { this.clearDom(); return el; }); } /** * 清除DOM内容 */ clearDom() { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); } /** * 获取默认数据 * @returns {Object} 默认数据对象 */ getDefaultData() { return { isMobile: appDiscountUtils.judgeMobile(), isRTL: appDiscountUtils.judgeRTL(), image_domain: this.win.SHOPLAZZA.image_domain, copyBtnClass: this.copyBtnClass, copyClass: this.copyClass } } /** * 复制优惠码功能 * @param {Element} el - 当前元素 */ copyCode(el) { const copyBtnList = el.querySelectorAll(`.${this.copyBtnClass}`); if (copyBtnList.length > 0) { copyBtnList.forEach(item => { item.onclick = async () => { // 确保获取正确的元素和内容 const codeElement = item.querySelector(`.${this.copyClass}`); if (!codeElement) return; // 获取纯文本内容 const textToCopy = codeElement.innerText.trim(); // 尝试使用现代API,如果失败则使用备用方案 try { if (navigator.clipboard && navigator.clipboard.writeText) { await navigator.clipboard.writeText(textToCopy); } else { throw new Error('Clipboard API not available'); } // 显示复制成功提示 this.showCopySuccessToast(textToCopy, el); } catch (err) { console.error('Modern clipboard API failed, trying fallback...', err); // 使用备用复制方案 this.fallbackCopy(textToCopy, el); } const discountId = item.dataset["discountId"]; // 跳转决策: is_redirection + link(可选覆盖) const setting = { is_redirection: item.dataset["redirection"] === "true", link: item.dataset["link"], }; const landingUrl = `/promotions/discount-default/${discountId}`; const finalUrl = appDiscountUtils.resolveDiscountHref(setting, landingUrl); if (finalUrl && appDiscountUtils.inProductBody(this.element)) { this.win.open(finalUrl, '_blank', 'noopener'); } } }) } } /** * 使用 execCommand 的复制方案 * @param {string} codeText - 要复制的文本 * @param {Element} el - 当前元素 */ fallbackCopy(codeText, el) { const textarea = this.win.document.createElement('textarea'); textarea.value = codeText; // 设置样式使文本框不可见 textarea.style.position = 'fixed'; textarea.style.left = '-9999px'; textarea.style.top = '0'; // 添加 readonly 属性防止移动端虚拟键盘弹出 textarea.setAttribute('readonly', 'readonly'); this.win.document.body.appendChild(textarea); textarea.focus(); textarea.select(); try { this.win.document.execCommand('copy'); // 显示复制成功提示 this.showCopySuccessToast(codeText, el); } catch (err) { console.error('Copy failed:', err); } this.win.document.body.removeChild(textarea); } /** * 创建 Toast 元素 * @returns {Element} 创建的 Toast 元素 */ createToastEl_() { const toast = document.createElement('ljs-toast'); toast.setAttribute('layout', 'nodisplay'); toast.setAttribute('hidden', ''); toast.setAttribute('id', 'discount-code-toast'); toast.style.zIndex = '1051'; return toast; } /** * 挂载 Toast 元素到 body * @returns {Element} 挂载的 Toast 元素 */ mountToastToBody_() { const existingToast = this.win.document.getElementById('discount-code-toast'); if (existingToast) { return existingToast; } const toast = this.createToastEl_(); this.win.document.body.appendChild(toast); return toast; } /** * 复制成功的提醒 * @param {string} codeText - 要复制的文本 * @param {Element} el - 当前元素 */ showCopySuccessToast(codeText, el) { const $toast = this.mountToastToBody_(); SPZ.whenApiDefined($toast).then(toast => { toast.showToast("Discount code copied !"); this.codeCopyInSessionStorage(codeText); }); } /** * 复制优惠码成功后要存一份到本地存储中,购物车使用 * @param {string} codeText - 要复制的文本 */ codeCopyInSessionStorage(codeText) { try { sessionStorage.setItem('other-copied-coupon', codeText); } catch (error) { console.error(error) } } } // 注册自定义元素 SPZ.defineElement('spz-custom-discount-code-model', SpzCustomDiscountCodeModel);
/** * Custom discount code component that handles displaying and managing discount codes * @extends {SPZ.BaseElement} */ class SpzCustomDiscountCode extends SPZ.BaseElement { constructor(element) { super(element); // API endpoint for fetching discount codes this.getDiscountCodeApi = "\/api\/storefront\/promotion\/code\/list"; // Debounce timer for resize events this.timer = null; // Current variant ID this.variantId = "74d676b3-5049-41c9-a689-64ac78929aa5"; // Store discount code data this.discountCodeData = {} } /** * Check if layout is supported * @param {string} layout - Layout type * @return {boolean} */ isLayoutSupported(layout) { return layout == SPZCore.Layout.LOGIC; } /** * Initialize component after build */ buildCallback() { this.templates_ = SPZServices.templatesForDoc(); this.viewport_ = this.getViewport(); // Bind methods to maintain context this.render = this.render.bind(this); this.resize = this.resize.bind(this); this.switchVariant = this.switchVariant.bind(this); } /** * Setup component when mounted */ mountCallback() { this.getData(); // Add event listeners this.viewport_.onResize(this.resize); this.win.document.addEventListener('dj.variantChange', this.switchVariant); } /** * Cleanup when component is unmounted */ unmountCallback() { this.viewport_.removeResize(this.resize); this.win.document.removeEventListener('dj.variantChange', this.switchVariant); // 清除定时器 if (this.timer) { clearTimeout(this.timer); this.timer = null; } } /** * Handle resize events with debouncing */ resize() { if (this.timer) { clearTimeout(this.timer) this.timer = null; } this.timer = setTimeout(() => { if (appDiscountUtils.inProductBody(this.element)) { this.render(); } else { this.renderSkeleton(); } }, 200); } /** * Handle variant changes * @param {Event} event - Variant change event */ switchVariant(event) { const variant = event.detail.selected; if (variant.product_id == '7e70c8b9-36e2-421f-a8f7-dc6f39c4cbd5' && variant.id != this.variantId) { this.variantId = variant.id; this.getData(); } } /** * Fetch discount code data from API */ getData() { if (appDiscountUtils.inProductBody(this.element)) { const reqBody = { product_id: "7e70c8b9-36e2-421f-a8f7-dc6f39c4cbd5", variant_id: this.variantId, product_type: "default", } if (!reqBody.product_id || !reqBody.variant_id) return; this.discountCodeData = {}; this.win.fetch(this.getDiscountCodeApi, { method: "POST", body: JSON.stringify(reqBody), headers: { "Content-Type": "application/json" } }).then(async (response) => { if (response.ok) { let data = await response.json(); if (data.list && data.list.length > 0) { data.list[0].product_setting.template_config = JSON.parse(data.list[0].product_setting.template_config); // Format timestamps to local timezone const zone = this.win.SHOPLAZZA.shop.time_zone; data.list = data.list.map(item => { if(+item.ends_at !== -1) { item.ends_at = appDiscountUtils.convertTimestampToFormat(+item.ends_at, zone); } item.starts_at = appDiscountUtils.convertTimestampToFormat(+item.starts_at, zone); return item; }); } this.discountCodeData = data; this.render(); } else { this.clearDom(); } }).catch(err => { console.error("discount_code", err) this.clearDom(); }); } else { this.renderSkeleton(); } } /** * Clear component DOM except template */ clearDom() { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); } /** * Render discount codes with formatted dates */ render() { // Render using discount code model SPZ.whenApiDefined(document.querySelector('#spz_custom_discount_code_model')).then(renderApi => { renderApi.doRender_({ discountCodeData: this.discountCodeData }) }).catch(err => { this.clearDom(); }) } renderSkeleton() { // Render template for non-product pages this.templates_ .findAndRenderTemplate(this.element, { isMobile: appDiscountUtils.judgeMobile() }) .then((el) => { this.clearDom(); this.element.appendChild(el); }) .catch(err => { this.clearDom(); }); } } // Register custom element SPZ.defineElement('spz-custom-discount-code', SpzCustomDiscountCode);
Style🌍Buy 2 Or More Free Shipping Worldwide🌍:  A
Quantity
Share the love
Free worldwide shipping
Free returns
Sustainably made
Secure payments
Description

🎃Make Your Porch the Best-Dressed House on the Block

Hang one on each side of your front door, porch columns, or party entrance to instantly give your home a festive Halloween look guests and trick-or-treaters will notice.


👻 OVERSIZED DECOR THAT ACTUALLY GETS NOTICED

Each vertical banner measures approximately 70.5 inches tall by 12 inches wide, creating plenty of visual impact from the sidewalk. The slim shape fits neatly beside most front doors without blocking the entrance.

🕸️ COORDINATED TWO-PIECE PORCH DISPLAY

The set includes two matching or complementary banners designed to frame your doorway. Together, they create a complete Halloween display without requiring piles of pumpkins, large inflatables, or complicated props.

🏡 DECORATE MORE THAN JUST THE FRONT DOOR

Hang the banners from porch posts, balcony railings, walls, fences, windows, entryways, or indoor party backdrops. They are a simple way to decorate homes, apartments, classrooms, offices, cafés, and Halloween events.

🔨 QUICK TO HANG—NO COMPLICATED SETUP

The top hanging cord makes installation fast and straightforward. Bottom corner grommets can be secured with string, hooks, or removable ties to help keep the banners in place during breezy weather.

♻️ EASY TO STORE AND REUSE NEXT HALLOWEEN

Unlike bulky seasonal decorations, the lightweight banners can be rolled or folded after the holiday. Store them in a drawer, closet, or decoration bin, then bring them back out for next year’s Halloween setup.


The following are realistic customer-style review examples for listing inspiration.

⭐⭐⭐⭐⭐ “Our porch finally looked decorated from the street.”

I usually place a few pumpkins near the door, but they are hard to see once it gets dark. These banners filled the empty space beside our doorway and made the whole entrance look much more finished. Hanging both took less than ten minutes.

Megan R., Columbus, Ohio

⭐⭐⭐⭐⭐ “Big impact without adding more clutter.”

Our porch is narrow, so I did not want another large inflatable or floor decoration. The banners hang flat beside the door and leave plenty of room for people to walk through. They looked great in family photos too.

Jason M., Austin, Texas

⭐⭐⭐⭐⭐ “Easy Halloween decorating for a busy family.”

I wanted something festive that I could put up quickly before the neighborhood trick-or-treat night. I hung one banner on each porch post and secured the bottom corners with small ties. They stayed straight and made the entrance feel ready for Halloween.

Samantha L., Toronto, Ontario


How to Use

1. Unroll the Banners

Remove both banners from the package and lay them flat for a short time. Gently smooth out any folds before hanging.

2. Choose the Display Area

Select two balanced locations beside your front door, on porch columns, along a wall, or at the entrance to your Halloween party.

3. Hang From the Top

Place the hanging cord over a secure hook, nail, railing, or removable outdoor hanger. Adjust each banner until both sides appear even.

4. Secure the Bottom Corners

Use the bottom grommets with string, reusable ties, or small hooks to reduce movement in windy conditions.

5. Store After the Season

Spot-clean when needed, allow the banners to dry completely, and roll or fold them for compact storage.


Specifications

Item Details
Product Type Halloween Vertical Porch Banner Set
Quantity 2 Banners
Size of Each Banner Approx. 70.5 × 12 in
Metric Size Approx. 179 × 30 cm
Display Direction Vertical
Installation Top hanging cord
Bottom Support Corner grommets
Recommended Locations Front door, porch, columns, balcony, wall, fence or party entrance
Recommended Environment Indoor or covered outdoor display
Care Instructions Spot-clean and air-dry
Seasonal Use Halloween and fall decorating
Package Includes 2 Halloween porch banners with hanging components as pictured

Frequently Asked Questions

Q: Does the package include one banner or two?

A: The product is sold as a coordinated set of two vertical banners, allowing you to decorate both sides of a doorway or entrance.

Q: Will the banners fit beside a standard front door?

A: Each banner is approximately 12 inches wide, so it can fit beside many standard doors, porch columns, and narrow entryways. Measuring the intended area before ordering is recommended.

Q: Can these banners be used outdoors?

A: Yes, they are suitable for covered porches and sheltered outdoor areas. Secure the bottom grommets during windy weather and bring the banners indoors during severe storms.

Q: Do I need special tools to install them?

A: No complicated tools are required. Hang the top cord from a secure hook or hanger, then use optional string or reusable ties at the bottom.

Q: What should I do if the banners arrive with creases?

A: Lay them flat, roll them gently in the opposite direction, or use low-temperature steam from the reverse side. Avoid placing high heat directly on the printed surface.

Q: Can the banners be washed?

A: Spot-cleaning with a soft, damp cloth is recommended. Allow the banners to air-dry completely before storing.

Q: Are different Halloween designs available?

A: Multiple artwork styles may be offered, including pumpkins, ghosts, witches, spiders, and Halloween lettering. Check the selected design carefully before placing your order.