← All changes
|
admin/modules/setup-wizard/components/Content/Complete.vue
+234
-176
3.12.3
→
3.13.3
View file →
| @@ -1,67 +1,71 @@ | ||
| 1 | 1 | <template> |
| 2 | - <div class="wpfnl-mm-complete"> | |
| 3 | - <!-- Header --> | |
| 4 | - <div class="wpfnl-mm-complete-header"> | |
| 5 | - <h2 class="wpfnl-mm-complete-title"> | |
| 6 | - {{ titleText }} | |
| 7 | - </h2> | |
| 8 | - <p class="wpfnl-mm-complete-subtitle"> | |
| 9 | - {{ subtitleText }} | |
| 2 | + <div class="wpfnl-wz-success" role="main"> | |
| 3 | + <!-- Sits behind the content; purely decorative --> | |
| 4 | + <canvas ref="confetti" class="wpfnl-wz-success__confetti" aria-hidden="true"></canvas> | |
| 5 | + | |
| 6 | + <div class="wpfnl-wz-success__body"> | |
| 7 | + <div class="wpfnl-wz-success__emoji" aria-hidden="true">🎉</div> | |
| 8 | + | |
| 9 | + <h1 class="wpfnl-wz-success__heading">Congratulations, You Did it!</h1> | |
| 10 | + <p class="wpfnl-wz-success__sub"> | |
| 11 | + WPFunnels is set up on your website! You're now ready to build | |
| 12 | + high-converting sales funnels. | |
| 10 | 13 | </p> |
| 11 | - </div> | |
| 12 | 14 | |
| 13 | - <!-- Video/Preview Section --> | |
| 14 | - <div class="wpfnl-mm-complete-video-wrapper"> | |
| 15 | - <div class="wpfnl-mm-complete-video"> | |
| 16 | - <!-- Poster Image --> | |
| 17 | - <div class="wpfnl-mm-complete-video-bg" v-show="!isVideoPlaying"> | |
| 18 | - <img | |
| 19 | - :src="posterImage" | |
| 20 | - alt="Video Poster" | |
| 21 | - class="wpfnl-mm-complete-video-image" | |
| 22 | - /> | |
| 23 | - <div class="wpfnl-mm-complete-video-overlay" @click="playVideo"></div> | |
| 24 | - </div> | |
| 25 | - <!-- YouTube iframe --> | |
| 26 | - <iframe | |
| 27 | - v-show="isVideoPlaying" | |
| 28 | - class="wpfnl-mm-complete-video-iframe" | |
| 29 | - :src="videoUrl" | |
| 30 | - title="WPFunnels Tutorial" | |
| 31 | - frameborder="0" | |
| 32 | - allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" | |
| 33 | - allowfullscreen | |
| 34 | - ></iframe> | |
| 35 | - <div class="wpfnl-mm-complete-video-player" v-show="!isVideoPlaying"> | |
| 36 | - <button class="wpfnl-mm-complete-play-btn" @click="playVideo"> | |
| 37 | - <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| 38 | - <path d="M4 2L14 8L4 14V2Z" fill="white"/> | |
| 39 | - </svg> | |
| 40 | - </button> | |
| 41 | - <div class="wpfnl-mm-complete-progress-bar"> | |
| 42 | - <div class="wpfnl-mm-complete-progress-fill"></div> | |
| 43 | - </div> | |
| 44 | - </div> | |
| 45 | - </div> | |
| 46 | - </div> | |
| 47 | - | |
| 48 | - <!-- Buttons Section --> | |
| 49 | - <div class="wpfnl-mm-complete-actions"> | |
| 50 | - <div class="wpfnl-mm-complete-buttons"> | |
| 51 | - <button class="wpfnl-mm-btn wpfnl-mm-btn-secondary" @click="goToDashboard"> | |
| 52 | - Go to Dashboard | |
| 15 | + <div class="wpfnl-wz-success__actions"> | |
| 16 | + <button | |
| 17 | + type="button" | |
| 18 | + class="wpfnl-wz-btn wpfnl-wz-btn--lg wpfnl-wz-btn--pill" | |
| 19 | + :class="hasFunnel ? 'wpfnl-wz-btn--ghost' : 'wpfnl-wz-btn--primary'" | |
| 20 | + @click="goToDashboard" | |
| 21 | + > | |
| 22 | + Explore dashboard | |
| 53 | 23 | </button> |
| 54 | 24 | |
| 55 | - <button class="wpfnl-mm-btn wpfnl-mm-btn-primary" @click="viewFunnel"> | |
| 56 | - {{ isStoreCheckout ? 'Go to Editor' : 'Test the Funnel' }} | |
| 57 | - <svg width="17" height="12" viewBox="0 0 17 12" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| 58 | - <path d="M1 6H16M16 6L11 1M16 6L11 11" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |
| 25 | + <button | |
| 26 | + v-if="hasFunnel" | |
| 27 | + type="button" | |
| 28 | + class="wpfnl-wz-btn wpfnl-wz-btn--primary wpfnl-wz-btn--lg wpfnl-wz-btn--pill" | |
| 29 | + @click="viewFunnel" | |
| 30 | + > | |
| 31 | + Customize your checkout | |
| 32 | + <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"> | |
| 33 | + <path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" /> | |
| 59 | 34 | </svg> |
| 60 | 35 | </button> |
| 61 | 36 | </div> |
| 62 | 37 | |
| 63 | - | |
| 38 | + <div class="wpfnl-wz-success__resources"> | |
| 39 | + <p class="wpfnl-wz-success__resources-title">Want to get more out of WPFunnels?</p> | |
| 40 | + | |
| 41 | + <div class="wpfnl-wz-success__resources-grid"> | |
| 42 | + <a | |
| 43 | + v-for="item in resources" | |
| 44 | + :key="item.label" | |
| 45 | + :href="item.url" | |
| 46 | + target="_blank" | |
| 47 | + rel="noreferrer noopener" | |
| 48 | + class="wpfnl-wz-success__resource-card" | |
| 49 | + > | |
| 50 | + <span class="wpfnl-wz-success__resource-icon" aria-hidden="true" v-html="item.icon"></span> | |
| 51 | + <span class="wpfnl-wz-success__resource-label">{{ item.label }}</span> | |
| 52 | + </a> | |
| 53 | + </div> | |
| 54 | + | |
| 55 | + <div class="wpfnl-wz-success__resources-footer"> | |
| 56 | + <p>These are always available from your dashboard.</p> | |
| 57 | + <p> | |
| 58 | + Want more power? | |
| 59 | + <a | |
| 60 | + href="https://getwpfunnels.com/pricing/" | |
| 61 | + target="_blank" | |
| 62 | + rel="noreferrer noopener" | |
| 63 | + class="wpfnl-wz-success__pro-link" | |
| 64 | + >See what Pro unlocks</a> | |
| 65 | + </p> | |
| 66 | + </div> | |
| 67 | + </div> | |
| 64 | 68 | </div> |
| 65 | 69 | </div> |
| 66 | 70 | </template> |
| 67 | 71 | |
| @@ -67,160 +71,214 @@ | ||
| 67 | 71 | |
| 68 | 72 | <script> |
| 69 | 73 | import apiFetch from '@wordpress/api-fetch'; |
| 70 | 74 | |
| 75 | +/** | |
| 76 | + * Canvas confetti for the completion screen. | |
| 77 | + * | |
| 78 | + * Returns handles so the caller can fade it out and then stop the loop — | |
| 79 | + * leaving a rAF running after the component unmounts would leak. | |
| 80 | + * | |
| 81 | + * @param {HTMLCanvasElement} canvas Target canvas. | |
| 82 | + * @return {{ startFade: Function, stop: Function }} Animation controls. | |
| 83 | + */ | |
| 84 | +function runConfetti( canvas ) { | |
| 85 | + const ctx = canvas.getContext( '2d' ); | |
| 86 | + const COLORS = [ '#6E42D3', '#a78bfa', '#fbbf24', '#34d399', '#f87171', '#60a5fa', '#f472b6' ]; | |
| 87 | + | |
| 88 | + let globalAlpha = 1; | |
| 89 | + let fading = false; | |
| 90 | + let animId; | |
| 91 | + | |
| 92 | + const pieces = Array.from( { length: 150 }, () => ( { | |
| 93 | + x: Math.random() * canvas.width, | |
| 94 | + y: Math.random() * canvas.height - canvas.height, | |
| 95 | + w: Math.random() * 10 + 5, | |
| 96 | + h: Math.random() * 5 + 3, | |
| 97 | + color: COLORS[ Math.floor( Math.random() * COLORS.length ) ], | |
| 98 | + speed: Math.random() * 3 + 1.5, | |
| 99 | + angle: Math.random() * Math.PI * 2, | |
| 100 | + spin: ( Math.random() - 0.5 ) * 0.1, | |
| 101 | + drift: ( Math.random() - 0.5 ) * 1.5, | |
| 102 | + } ) ); | |
| 103 | + | |
| 104 | + const draw = () => { | |
| 105 | + ctx.clearRect( 0, 0, canvas.width, canvas.height ); | |
| 106 | + | |
| 107 | + if ( fading ) { | |
| 108 | + globalAlpha = Math.max( 0, globalAlpha - 0.018 ); | |
| 109 | + } | |
| 110 | + | |
| 111 | + if ( globalAlpha <= 0 ) { | |
| 112 | + return; | |
| 113 | + } | |
| 114 | + | |
| 115 | + pieces.forEach( ( p ) => { | |
| 116 | + ctx.save(); | |
| 117 | + ctx.globalAlpha = globalAlpha; | |
| 118 | + ctx.translate( p.x + p.w / 2, p.y + p.h / 2 ); | |
| 119 | + ctx.rotate( p.angle ); | |
| 120 | + ctx.fillStyle = p.color; | |
| 121 | + ctx.fillRect( -p.w / 2, -p.h / 2, p.w, p.h ); | |
| 122 | + ctx.restore(); | |
| 123 | + | |
| 124 | + p.y += p.speed; | |
| 125 | + p.x += p.drift; | |
| 126 | + p.angle += p.spin; | |
| 127 | + | |
| 128 | + if ( p.y > canvas.height + p.h ) { | |
| 129 | + p.y = -p.h; | |
| 130 | + p.x = Math.random() * canvas.width; | |
| 131 | + } | |
| 132 | + } ); | |
| 133 | + | |
| 134 | + animId = requestAnimationFrame( draw ); | |
| 135 | + }; | |
| 136 | + | |
| 137 | + draw(); | |
| 138 | + | |
| 139 | + return { | |
| 140 | + startFade: () => { | |
| 141 | + fading = true; | |
| 142 | + }, | |
| 143 | + stop: () => cancelAnimationFrame( animId ), | |
| 144 | + }; | |
| 145 | +} | |
| 146 | + | |
| 71 | 147 | export default { |
| 72 | 148 | name: 'Complete', |
| 73 | 149 | props: { |
| 74 | 150 | funnelId: { |
| 75 | - type: [Number, String], | |
| 76 | - default: null | |
| 151 | + type: [ Number, String ], | |
| 152 | + default: null, | |
| 77 | 153 | }, |
| 78 | 154 | firstStepLink: { |
| 79 | 155 | type: String, |
| 80 | - default: '' | |
| 156 | + default: '', | |
| 81 | 157 | }, |
| 82 | - selectedGoal: { | |
| 83 | - type: String, | |
| 84 | - default: 'sales' | |
| 85 | - }, | |
| 86 | - agreeToShare: { | |
| 87 | - type: Boolean, | |
| 88 | - default: false | |
| 89 | - } | |
| 90 | 158 | }, |
| 159 | + emits: [ 'nav' ], | |
| 91 | 160 | data() { |
| 92 | 161 | return { |
| 93 | - isVideoPlaying: false, | |
| 94 | - posterImage: this.getPosterImage(), | |
| 95 | - videoUrl: '', | |
| 96 | - contactRequestInFlight: false, | |
| 97 | - contactCreated: false, | |
| 98 | - } | |
| 162 | + fadeTimer: null, | |
| 163 | + confetti: null, | |
| 164 | + resources: [ | |
| 165 | + { | |
| 166 | + label: 'Blog & tutorials', | |
| 167 | + url: 'https://www.youtube.com/@WPFunnels', | |
| 168 | + icon: '<svg width="28" height="28" viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="8" fill="#fee2e2"/><path d="M11 10l7 4-7 4V10z" fill="#ef4444"/></svg>', | |
| 169 | + }, | |
| 170 | + { | |
| 171 | + label: 'Join the community', | |
| 172 | + url: 'https://www.facebook.com/groups/wpfunnels', | |
| 173 | + icon: '<svg width="28" height="28" viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="8" fill="#dbeafe"/><circle cx="12" cy="12" r="3" stroke="#3b82f6" stroke-width="1.4"/><circle cx="18" cy="12" r="3" stroke="#3b82f6" stroke-width="1.4"/><path d="M7 22c0-2.8 2-4.5 5-4.5M21 22c0-2.8-2-4.5-5-4.5" stroke="#3b82f6" stroke-width="1.4" stroke-linecap="round"/></svg>', | |
| 174 | + }, | |
| 175 | + { | |
| 176 | + label: 'Get support', | |
| 177 | + url: 'https://wordpress.org/support/plugin/wpfunnels/', | |
| 178 | + icon: '<svg width="28" height="28" viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="8" fill="#d1fae5"/><path d="M10 14v-2a4 4 0 018 0v2" stroke="#059669" stroke-width="1.4" stroke-linecap="round"/><rect x="8" y="14" width="3" height="4" rx="1.5" fill="#059669"/><rect x="17" y="14" width="3" height="4" rx="1.5" fill="#059669"/></svg>', | |
| 179 | + }, | |
| 180 | + { | |
| 181 | + label: 'Docs', | |
| 182 | + url: 'https://getwpfunnels.com/docs/getting-started-with-wpfunnels/', | |
| 183 | + icon: '<svg width="28" height="28" viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="8" fill="#e0f2fe"/><rect x="8" y="7" width="12" height="14" rx="2" stroke="#0284c7" stroke-width="1.4"/><path d="M11 12h6M11 15.5h4" stroke="#0284c7" stroke-width="1.4" stroke-linecap="round"/></svg>', | |
| 184 | + }, | |
| 185 | + ], | |
| 186 | + }; | |
| 99 | 187 | }, |
| 188 | + computed: { | |
| 189 | + /** | |
| 190 | + * Whether the template step actually built something. False when the | |
| 191 | + * user skipped it, in which case there is no funnel to open and the | |
| 192 | + * editor CTA is hidden. | |
| 193 | + */ | |
| 194 | + hasFunnel() { | |
| 195 | + return !! this.funnelId; | |
| 196 | + }, | |
| 197 | + }, | |
| 100 | 198 | mounted() { |
| 101 | - this.maybeCreateContact(); | |
| 199 | + // The completion screen is terminal — the footer offers no way onward. | |
| 200 | + this.$emit( 'nav', { | |
| 201 | + showBack: false, | |
| 202 | + showNext: false, | |
| 203 | + showSkip: false, | |
| 204 | + canProceed: false, | |
| 205 | + busy: false, | |
| 206 | + label: '', | |
| 207 | + } ); | |
| 208 | + | |
| 209 | + this.startConfetti(); | |
| 102 | 210 | }, |
| 103 | - computed: { | |
| 104 | - isStoreCheckout() { | |
| 105 | - return this.selectedGoal === 'improve-checkout'; | |
| 106 | - }, | |
| 107 | - titleText() { | |
| 108 | - if (this.isStoreCheckout) { | |
| 109 | - return `Your store checkout is ready! 🎉`; | |
| 110 | - } | |
| 111 | - return `Your funnel is live 🎉`; | |
| 112 | - }, | |
| 113 | - subtitleText() { | |
| 114 | - if (this.isStoreCheckout) { | |
| 115 | - return `Your optimized checkout is set up. Customers will now experience a streamlined checkout flow designed to reduce cart abandonment and boost conversions.`; | |
| 116 | - } | |
| 117 | - if (this.selectedGoal === 'leads') { | |
| 118 | - return `Your first funnel is set up. Visitors opting in here will now see your next offer. Once leads start coming in, we'll show you exactly how this funnel is growing your list.`; | |
| 119 | - } | |
| 120 | - return `Your first funnel is set up. Customers who purchase this product will now see your order bump and upsell offers. Once real orders start coming in, we'll show you exactly how much additional revenue this funnel generates.`; | |
| 121 | - }, | |
| 122 | - infoText() { | |
| 123 | - if (this.isStoreCheckout) { | |
| 124 | - return `You can customize your checkout page further from the funnel editor.`; | |
| 125 | - } | |
| 126 | - if (this.selectedGoal === 'leads') { | |
| 127 | - return `Once this funnel starts bringing in leads, you can clone it for your other offers in just a few clicks.`; | |
| 128 | - } | |
| 129 | - return `Once you see this funnel working, you can clone it for your other products in a few clicks.`; | |
| 130 | - } | |
| 211 | + beforeUnmount() { | |
| 212 | + this.stopConfetti(); | |
| 131 | 213 | }, |
| 132 | 214 | methods: { |
| 133 | - maybeCreateContact() { | |
| 134 | - if (!this.agreeToShare || this.contactCreated || this.contactRequestInFlight) { | |
| 215 | + startConfetti() { | |
| 216 | + const canvas = this.$refs.confetti; | |
| 217 | + if ( ! canvas ) { | |
| 135 | 218 | return; |
| 136 | 219 | } |
| 137 | 220 | |
| 221 | + canvas.width = window.innerWidth; | |
| 222 | + canvas.height = window.innerHeight; | |
| 223 | + | |
| 224 | + this.confetti = runConfetti( canvas ); | |
| 225 | + this.fadeTimer = setTimeout( this.confetti.startFade, 3200 ); | |
| 226 | + }, | |
| 227 | + | |
| 228 | + stopConfetti() { | |
| 229 | + clearTimeout( this.fadeTimer ); | |
| 230 | + this.confetti?.stop(); | |
| 231 | + }, | |
| 232 | + | |
| 233 | + /** | |
| 234 | + * Report the outcome before leaving the wizard. | |
| 235 | + * | |
| 236 | + * @param {string} action Which exit the user took. | |
| 237 | + * @return {Promise} Always resolves. | |
| 238 | + */ | |
| 239 | + completeStep( action ) { | |
| 138 | 240 | const wizardObj = window.setup_wizard_obj || {}; |
| 139 | - const restApiUrl = wizardObj.rest_api_url; | |
| 140 | - if (!restApiUrl) { | |
| 141 | - return; | |
| 241 | + const restApiUrl = wizardObj.rest_api_url || ''; | |
| 242 | + | |
| 243 | + if ( ! restApiUrl ) { | |
| 244 | + return Promise.resolve(); | |
| 142 | 245 | } |
| 143 | 246 | |
| 144 | - const payload = { | |
| 145 | - email: wizardObj.admin_email, | |
| 146 | - name: wizardObj.admin_name | |
| 147 | - }; | |
| 247 | + const base = restApiUrl.endsWith( '/' ) ? restApiUrl : `${ restApiUrl }/`; | |
| 148 | 248 | |
| 149 | - this.contactRequestInFlight = true; | |
| 150 | - apiFetch({ | |
| 151 | - path: `${restApiUrl}wpfunnels/v1/settings/create-contact/`, | |
| 249 | + return apiFetch( { | |
| 250 | + url: `${ base }wpfunnels/v1/setup-wizard/complete-step`, | |
| 152 | 251 | method: 'POST', |
| 153 | - data: payload | |
| 154 | - }) | |
| 155 | - .then(() => { | |
| 156 | - this.contactCreated = true; | |
| 157 | - }) | |
| 158 | - .catch(error => { | |
| 159 | - console.error('Error creating contact:', error); | |
| 160 | - }) | |
| 161 | - .finally(() => { | |
| 162 | - this.contactRequestInFlight = false; | |
| 163 | - }); | |
| 164 | - }, | |
| 165 | - getPosterImage() { | |
| 166 | - // Use the video poster from setup wizard object | |
| 167 | - const wizardObj = window.setup_wizard_obj || {} | |
| 168 | - return wizardObj.wizard_video_poster || '' | |
| 169 | - }, | |
| 170 | - handleCompleteStep(action) { | |
| 171 | - const wizardObj = window.setup_wizard_obj || {} | |
| 172 | - const restApiUrl = wizardObj.rest_api_url || wizardObj.rest_url || '' | |
| 173 | - const totalSteps = this.selectedGoal === 'sales' ? 7 | |
| 174 | - : (this.selectedGoal === 'order-value' || this.selectedGoal === 'improve-checkout') ? 6 | |
| 175 | - : 5; | |
| 176 | - const requestArgs = { | |
| 177 | - method: 'POST', | |
| 178 | 252 | data: { |
| 179 | 253 | funnelId: this.funnelId, |
| 180 | - action: action, | |
| 181 | - goal: this.selectedGoal, | |
| 182 | - total_steps: totalSteps, | |
| 183 | - } | |
| 184 | - } | |
| 254 | + action, | |
| 255 | + goal: 'improve-checkout', | |
| 256 | + total_steps: 4, | |
| 257 | + }, | |
| 258 | + } ).catch( () => {} ); | |
| 259 | + }, | |
| 185 | 260 | |
| 186 | - if (restApiUrl) { | |
| 187 | - const normalizedRestUrl = restApiUrl.endsWith('/') ? restApiUrl : `${restApiUrl}/` | |
| 188 | - requestArgs.url = `${normalizedRestUrl}wpfunnels/v1/setup-wizard/complete-step` | |
| 189 | - } else { | |
| 190 | - requestArgs.path = '/wpfunnels/v1/setup-wizard/complete-step' | |
| 191 | - } | |
| 261 | + async viewFunnel() { | |
| 262 | + await this.completeStep( 'viewFunnel' ); | |
| 263 | + const wizardObj = window.setup_wizard_obj || {}; | |
| 264 | + const adminUrl = wizardObj.admin_url || ''; | |
| 192 | 265 | |
| 193 | - return apiFetch(requestArgs).catch(() => {}) | |
| 194 | - }, | |
| 195 | - async viewFunnel() { | |
| 196 | - this.maybeCreateContact(); | |
| 197 | - await this.handleCompleteStep('viewFunnel') | |
| 198 | - const wizardObj = window.setup_wizard_obj || {} | |
| 199 | - if (this.isStoreCheckout) { | |
| 200 | - const adminUrl = wizardObj.admin_url || '' | |
| 201 | - window.location.href = `${adminUrl}admin.php?page=edit_funnel&id=${this.funnelId}` | |
| 202 | - return | |
| 266 | + if ( this.funnelId ) { | |
| 267 | + window.location.href = `${ adminUrl }admin.php?page=edit_funnel&id=${ this.funnelId }`; | |
| 268 | + return; | |
| 203 | 269 | } |
| 204 | - if (this.firstStepLink) { | |
| 205 | - window.open(this.firstStepLink, '_blank') | |
| 206 | - } else { | |
| 207 | - window.location.href = wizardObj.dashboard_url || `${wizardObj.admin_url}admin.php?page=wpfunnels` | |
| 270 | + if ( this.firstStepLink ) { | |
| 271 | + window.open( this.firstStepLink, '_blank' ); | |
| 272 | + return; | |
| 208 | 273 | } |
| 274 | + window.location.href = wizardObj.dashboard_url || `${ adminUrl }admin.php?page=wpfunnels`; | |
| 209 | 275 | }, |
| 276 | + | |
| 210 | 277 | async goToDashboard() { |
| 211 | - this.maybeCreateContact(); | |
| 212 | - await this.handleCompleteStep('goToDashboard') | |
| 213 | - const wizardObj = window.setup_wizard_obj || {} | |
| 214 | - window.location.href = wizardObj.dashboard_url || `${wizardObj.admin_url}admin.php?page=wpfunnels` | |
| 278 | + await this.completeStep( 'goToDashboard' ); | |
| 279 | + const wizardObj = window.setup_wizard_obj || {}; | |
| 280 | + window.location.href = wizardObj.dashboard_url || `${ wizardObj.admin_url }admin.php?page=wpfunnels`; | |
| 215 | 281 | }, |
| 216 | - playVideo() { | |
| 217 | - // Set video URL with autoplay and show the iframe | |
| 218 | - this.videoUrl = 'https://www.youtube.com/embed/GrzIRl5jfBE?autoplay=1&rel=0' | |
| 219 | - this.isVideoPlaying = true | |
| 220 | - }, | |
| 221 | - showHelp() { | |
| 222 | - window.open('https://getwpfunnels.com/docs/', '_blank') | |
| 223 | - } | |
| 224 | - } | |
| 225 | -} | |
| 282 | + }, | |
| 283 | +}; | |
| 226 | 284 | </script> |