中国P站

achievements

Hard work pays off

We couldn't have done this without our incredible team and amazing clients.

Photo of a lot of people working on the same table on their laptops

Our achievements

The mobile games industry moves fast. So do we. Keep up with the latest 中国P站 news.

Logo Deloitte

November 2022

#31 2022 Deloitte Technology Fast 500鈩

Logo Deloitte

November 2022

#5 2022 Deloitte Technology Fast 50鈩

Logo The Globe And Mail

SEPTEMBER 2021

#2 Canada's Top Growing Companies

Logo of 中国P站's partner Adjust

SEPTEMBER 2021

Featured as a Top Ranked Company

Logo of 中国P站's partner Appsflyer

MARCH 2021

#5 on AppsFlyer's Global IAP Index

Logo of 中国P站's partner Singular

FEBRUARY 2021

Top media source in Singular's 2021 ROI Index

Logo Deloitte

NOVEMBER 2020

#4 in the Fast 50
#16 in the Fast 500

Logo Canadian Business

OCTOBER 2020

#7 Canadian Business' 2020 Startup List

Logo of 中国P站's partner Appsflyer

OCTOBER 2020

#7 AppsFlyer's Best Media Sources for Mobile Advertising

Logo L'actualit茅

SEPTEMBER 2020

#1 Fastest Growing Company in Quebec

Logo The Globe And Mail

SEPTEMBER 2020

#4 Fastest Growing Company in Canada

Logo Kochava

惭础驰听2020

#2 Cleanest Traffic in the Industry

Logo of 中国P站's partner Appsflyer

MARCH 2020

#7 Global Gaming Performance Index

Logo Deloitte

NOVEMBER 2019

One of Canada's Companies-to-Watch

Logo Maclean's

SEPTEMBER 2019

#36 Fastest Growing Startup in Canada

Terms of UsePrivacy PolicyPrivacy Center
) is missing or failed to load."); return; } var result = window.AF_SMART_SCRIPT.generateOneLinkURL({ oneLinkURL: oneLinkURL, afParameters: { mediaSource: mediaSource, campaign: campaign, adSet: adSet, ad: ad, channel: channel, afCustom: [ is_retargeting, af_dp, af_prt, af_pmod_priority, af_pmod_priority, custom_ss_ui ], deepLinkValue: deepLinkValue } }); if (result && result.clickURL) { renderQrCodesInBulk(result.clickURL); updateCtaLinksInBulk(result.clickURL); if (typeof window.AF_SMART_SCRIPT.fireImpressionsLink === 'function') { window.AF_SMART_SCRIPT.fireImpressionsLink(); } } else { console.error("AppsFlyer Error: OneLink URL generation failed."); } } /* ========================================= SECTION 2: TICKER LOGIC (Mobile Fixed + Truncated) ========================================= */ function initDynamicCounter() { const container = document.getElementById("dynamicCounter"); if (!container) return; const config = { startDateUTC: "2025-09-24 00:00:00", startValue: 205074441, incrementPerSecond: 1.84, }; function parseUTC(dateString) { const isoString = dateString.trim().replace(" ", "T") + "Z"; return Date.parse(isoString); } const startTimestamp = parseUTC(config.startDateUTC); // Check if timestamp is valid before proceeding if (isNaN(startTimestamp)) { console.error("Invalid start date configuration. Counter cannot initialize."); return; } function getCurrentRawValue() { const now = Date.now(); const secondsPassed = (now - startTimestamp) / 1000; // Return the full value including decimals (the TRUE value) return config.startValue + (secondsPassed * config.incrementPerSecond); } function formatCurrency(number) { // Use Math.floor ONLY for display purposes (to truncate/round down) const truncatedNumber = Math.floor(number); return ( "$" + truncatedNumber.toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: 0, }) ); } // --- INITIALIZATION --- let currentRawValue = getCurrentRawValue(); // Holds the full decimal value let currentValue = Math.floor(currentRawValue); // Holds the currently displayed whole dollar value let currentString = formatCurrency(currentRawValue); container.innerHTML = ''; // Clear static text // Build initial slots currentString.split('').forEach(char => { const slot = document.createElement('div'); slot.className = 'char-slot'; const charEl = document.createElement('span'); charEl.className = 'char-value'; charEl.textContent = char; slot.appendChild(charEl); container.appendChild(slot); }); // --- END INITIALIZATION --- function updateCounter() { const newRawValue = getCurrentRawValue(); // Get the new whole dollar value for comparison const newValue = Math.floor(newRawValue); // 1. Check if the whole dollar value has changed (newValue > currentValue) if (newValue <= currentValue) { // If the whole number hasn't changed, just update the raw value and exit. currentRawValue = newRawValue; return; } // 2. If the value has changed, generate the new display string const newString = formatCurrency(newRawValue); const oldString = currentString; // Update the base values for the next cycle currentRawValue = newRawValue; currentValue = newValue; currentString = newString; // Handle case where the number of digits changes (e.g., crossing 100 million) if (newString.length !== oldString.length) { // Rebuild all slots if length changes container.innerHTML = ''; newString.split('').forEach(char => { const slot = document.createElement('div'); slot.className = 'char-slot'; const charEl = document.createElement('span'); charEl.className = 'char-value'; charEl.textContent = char; slot.appendChild(charEl); container.appendChild(slot); }); return; } // 3. Animate Changes const slots = container.children; for (let i = 0; i < newString.length; i++) { if (newString[i] !== oldString[i]) { const currentSlot = slots[i]; const oldElement = currentSlot.lastElementChild; const nextElement = document.createElement('span'); nextElement.className = 'char-value slide-in'; nextElement.textContent = newString[i]; if (oldElement) { oldElement.classList.add('slide-out'); oldElement.classList.remove('slide-in'); } currentSlot.appendChild(nextElement); // Clean up old element after animation setTimeout(() => { if (oldElement && oldElement.parentNode === currentSlot) { currentSlot.removeChild(oldElement); } }, 500); } } } // Set the counter to update every second (1000 milliseconds) setInterval(updateCounter, 1000); } /* ========================================= SECTION 3: SLIDER LOGIC (Swiper) ========================================= */ function initTestimonialsSlider() { const testimonialsSlider = new Swiper(".testimonials_slider_collection", { slidesPerView: "auto", slideClass: "testimonials_slider_slide", loop: true, pagination: { el: ".testimonials_slider_pagination", bulletActiveClass: "is-active", bulletClass: "testimonials_slider_bullet", clickable: true, }, navigation: { nextEl: "[testimonials-slider-arrow='next']", prevEl: "[testimonials-slider-arrow='prev']", }, }); } function initBlogSlider() { const blogSlider = new Swiper(".blog_collection", { slidesPerView: "auto", slideClass: "blog_slide", loop: true, pagination: { el: ".blog_pagination", bulletActiveClass: "active", bulletClass: "blog_bullet", clickable: true, }, navigation: { nextEl: "[blog-slider-arrow='next']", prevEl: "[blog-slider-arrow='prev']", }, }); } function initVideoSlider() { const videoSlider = new Swiper(".video_slider_collection", { slidesPerView: "auto", slideClass: "video_slider_slide", loop: true, pagination: { el: ".video_slider_pagination", bulletActiveClass: "is-active", bulletClass: "video_slider_bullet", clickable: true, }, navigation: { nextEl: "[video-slider-arrow='next']", prevEl: "[video-slider-arrow='prev']", }, }); } /* ========================================= SECTION 4: YOUTUBE ENDSCREEN HIDER (REMOVED) ========================================= */ // The YouTube API functions and logic have been removed. /* ========================================= SECTION 5: INITIALIZATION ========================================= */ document.addEventListener("DOMContentLoaded", function () { initDynamicCounter(); // Ticker applyOneLinkUrl(); // AppsFlyer initTestimonialsSlider(); // Slider 1 initBlogSlider(); // Slider 2 initVideoSlider(); // Slider 3 // loadYoutubeAPI(); // Removed // initLightboxPlayerControl(); // Removed }); // init Weglot Weglot.initialize({ api_key: 'wg_69b690c4cd1390b9bc6f4c63627846524' }); // on Weglot init Weglot.on('initialized', ()=>{ // get the current active language const currentLang = Weglot.getCurrentLang(); // call updateFlagDropdownLinks function updateSW6FlagDropdownLinks(currentLang); }); // for each of the .wg-element-wrapper language links document.querySelectorAll('.wg-element-wrapper.sw6 [lang]').forEach((link)=>{ // add a click event listener link.addEventListener('click', function(e){ // prevent default e.preventDefault(); // switch to the current active language Weglot.switchTo(this.getAttribute('lang')); // call updateDropdownLinks function updateSW6FlagDropdownLinks(this.getAttribute('lang')); }); }); // updateFlagDropdownLinks function function updateSW6FlagDropdownLinks(currentLang){ // get the wrapper element const $wrapper = document.querySelector('.wg-element-wrapper.sw6'); // if the .w-dropdown-toggle is not the current active language if($wrapper.querySelector('.w-dropdown-toggle').getAttribute('lang') !== currentLang){ // swap the dropdown toggle's innerHTML with the current active language link innerHTML const $activeLangLink = $wrapper.querySelector('[lang='+currentLang+']'); const childDiv = $activeLangLink.innerHTML; const $toggle = $wrapper.querySelector('.w-dropdown-toggle'); const toggleDiv = $toggle.innerHTML; $toggle.innerHTML = childDiv; $activeLangLink.innerHTML = toggleDiv; // swap the dropdown toggle's lang attr with the current active language link lang attr const lang = $activeLangLink.getAttribute('lang'); const toggleLang = $toggle.getAttribute('lang'); $toggle.setAttribute('lang', lang); $activeLangLink.setAttribute('lang', toggleLang); } }