CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vkontakte--vk-bridge

Bridge library for VK Mini Apps to communicate with VK clients across iOS, Android, and Web platforms

Pending
Overview
Eval results
Files

advertising-monetization.mddocs/

Advertising & Monetization

Advertising integration including native ads, banner ads, conversion tracking, and monetization features for VK Mini Apps.

Capabilities

Banner Advertising

Display and manage banner advertisements within the Mini App interface.

/**
 * Show banner advertisement
 * @param props - Banner ad configuration
 */
function send(method: 'VKWebAppShowBannerAd', props: ShowBannerAdRequest): Promise<VKWebAppShowBannerAdResponse>;

/**
 * Check banner ad availability
 */
function send(method: 'VKWebAppCheckBannerAd'): Promise<VKWebAppCheckBannerAdResponse>;

/**
 * Hide currently displayed banner ad
 */
function send(method: 'VKWebAppHideBannerAd'): Promise<VKWebAppHideBannerAdResponse>;

interface ShowBannerAdRequest {
  /** Banner placement location */
  banner_location: BannerAdLocation;
}

enum BannerAdLocation {
  TOP = 'top',
  BOTTOM = 'bottom'
}

interface VKWebAppShowBannerAdResponse {
  result: boolean;
}

interface VKWebAppCheckBannerAdResponse {
  result: boolean;
}

interface VKWebAppHideBannerAdResponse {
  result: boolean;
}

Native Advertising

Display native ads that blend with app content for better user experience.

/**
 * Show native advertisements
 * @param props.ad_format - Type of native ad format
 * @param props.use_waterfall - Use waterfall ad loading (optional)
 */
function send(method: 'VKWebAppShowNativeAds', props: {
  ad_format: EAdsFormats;
  use_waterfall?: boolean;
}): Promise<{ result: true }>;

/**
 * Check native ad availability
 * @param props.ad_format - Type of native ad format to check
 * @param props.use_waterfall - Use waterfall ad loading (optional)
 */
function send(method: 'VKWebAppCheckNativeAds', props: {
  ad_format: EAdsFormats;
  use_waterfall?: boolean;
}): Promise<{ result: boolean }>;

enum EAdsFormats {
  REWARD = 'reward',
  INTERSTITIAL = 'interstitial'
}

Analytics & Tracking

Track user interactions and conversions for advertising optimization.

/**
 * Fire retargeting pixel for user tracking
 * @param props - Retargeting pixel configuration
 */
function send(method: 'VKWebAppRetargetingPixel', props: RetargetingPixelOptions): Promise<{
  result: true;
}>;

/**
 * Track conversion events
 * @param props.pixel_code - Pixel tracking code
 * @param props.conversion_event - Event identifier
 * @param props.conversion_value - Event value
 */
function send(method: 'VKWebAppConversionHit', props: {
  pixel_code: string;
  conversion_event: string;
  conversion_value: number;
}): Promise<{ result: true }>;

interface RetargetingPixelOptions {
  /** Pixel tracking code */
  pixel_code: string;
  /** Custom parameters */
  custom_params?: Record<string, string | number>;
}

Usage Examples:

// Check and show banner ads
const bannerAvailable = await bridge.send('VKWebAppCheckBannerAd');

if (bannerAvailable.result) {
  const bannerResult = await bridge.send('VKWebAppShowBannerAd', {
    banner_location: BannerAdLocation.BOTTOM
  });
  
  console.log('Banner ad shown:', bannerResult.result);
} else {
  console.log('Banner ads not available');
}

// Show rewarded video ads
const rewardedAdsAvailable = await bridge.send('VKWebAppCheckNativeAds', {
  ad_format: EAdsFormats.REWARD
});

if (rewardedAdsAvailable.result) {
  await bridge.send('VKWebAppShowNativeAds', {
    ad_format: EAdsFormats.REWARD,
    use_waterfall: true
  });
  
  // Listen for ad completion event
  bridge.subscribe((event) => {
    if (event.detail.type === 'VKWebAppShowNativeAdsResult') {
      console.log('Rewarded ad completed - give user reward');
      giveUserReward();
    }
  });
}

// Track conversion events
await bridge.send('VKWebAppConversionHit', {
  pixel_code: 'your-pixel-code',
  conversion_event: 'purchase',
  conversion_value: 100
});

// Track retargeting pixel
await bridge.send('VKWebAppRetargetingPixel', {
  pixel_code: 'your-retargeting-pixel',
  custom_params: {
    user_id: '12345',
    category: 'gaming',
    value: 50
  }
});

Monetization Strategies

Ad-Based Revenue

class AdManager {
  private adShownCount = 0;
  private rewardedAdCooldown = 0;

  async showInterstitialAd(): Promise<boolean> {
    const available = await bridge.send('VKWebAppCheckNativeAds', {
      ad_format: EAdsFormats.INTERSTITIAL
    });

    if (available.result) {
      await bridge.send('VKWebAppShowNativeAds', {
        ad_format: EAdsFormats.INTERSTITIAL
      });
      this.adShownCount++;
      return true;
    }

    return false;
  }

  async showRewardedAd(): Promise<boolean> {
    if (Date.now() < this.rewardedAdCooldown) {
      console.log('Rewarded ad on cooldown');
      return false;
    }

    const available = await bridge.send('VKWebAppCheckNativeAds', {
      ad_format: EAdsFormats.REWARD
    });

    if (available.result) {
      await bridge.send('VKWebAppShowNativeAds', {
        ad_format: EAdsFormats.REWARD
      });
      
      // Set cooldown (e.g., 5 minutes)
      this.rewardedAdCooldown = Date.now() + 5 * 60 * 1000;
      return true;
    }

    return false;
  }

  async manageBannerAds(): Promise<void> {
    const available = await bridge.send('VKWebAppCheckBannerAd');
    
    if (available.result) {
      // Show banner at bottom
      await bridge.send('VKWebAppShowBannerAd', {
        banner_location: BannerAdLocation.BOTTOM
      });
      
      // Hide after certain actions
      setTimeout(async () => {
        await bridge.send('VKWebAppHideBannerAd');
      }, 30000); // Hide after 30 seconds
    }
  }
}

const adManager = new AdManager();

// Show ads at appropriate moments
document.getElementById('show-interstitial')?.addEventListener('click', async () => {
  await adManager.showInterstitialAd();
});

document.getElementById('get-reward')?.addEventListener('click', async () => {
  const success = await adManager.showRewardedAd();
  if (success) {
    console.log('User will receive reward after ad completion');
  }
});

Conversion Tracking Framework

class ConversionTracker {
  private pixelCode: string;

  constructor(pixelCode: string) {
    this.pixelCode = pixelCode;
  }

  async trackEvent(event: string, value: number = 0, customParams?: Record<string, any>): Promise<void> {
    try {
      // Track conversion
      await bridge.send('VKWebAppConversionHit', {
        pixel_code: this.pixelCode,
        conversion_event: event,
        conversion_value: value
      });

      // Track retargeting with custom parameters
      if (customParams) {
        await bridge.send('VKWebAppRetargetingPixel', {
          pixel_code: this.pixelCode,
          custom_params: customParams
        });
      }

      console.log(`Tracked ${event} with value ${value}`);
    } catch (error) {
      console.error('Failed to track conversion:', error);
    }
  }

  async trackPurchase(amount: number, productId: string): Promise<void> {
    await this.trackEvent('purchase', amount, {
      product_id: productId,
      timestamp: Date.now()
    });
  }

  async trackRegistration(userId: string): Promise<void> {
    await this.trackEvent('registration', 0, {
      user_id: userId,
      timestamp: Date.now()
    });
  }

  async trackLevelComplete(level: number): Promise<void> {
    await this.trackEvent('level_complete', level, {
      level: level,
      timestamp: Date.now()
    });
  }
}

// Usage
const tracker = new ConversionTracker('your-pixel-code');

// Track different events
await tracker.trackPurchase(100, 'premium_month');
await tracker.trackRegistration('user123');
await tracker.trackLevelComplete(5);

Hybrid Monetization

// Combine ads and payments for optimal revenue
class MonetizationManager {
  private paymentManager: PaymentManager;
  private adManager: AdManager;
  private tracker: ConversionTracker;

  constructor() {
    this.paymentManager = new PaymentManager(51665960, 12345);
    this.adManager = new AdManager();
    this.tracker = new ConversionTracker('pixel-code');
  }

  async unlockPremiumContent(contentId: string): Promise<boolean> {
    // Offer choice: pay or watch ads
    const choice = await this.showMonetizationChoice();

    if (choice === 'payment') {
      const success = await this.paymentManager.purchaseProduct({
        id: contentId,
        name: 'Premium Content',
        description: 'Unlock premium content',
        price: 5000, // 50 rubles
        category: 'consumable'
      }, getCurrentUserId());

      if (success) {
        await this.tracker.trackPurchase(5000, contentId);
        return true;
      }
    } else if (choice === 'ads') {
      const adSuccess = await this.adManager.showRewardedAd();
      
      if (adSuccess) {
        // Wait for ad completion
        return new Promise((resolve) => {
          bridge.subscribe((event) => {
            if (event.detail.type === 'VKWebAppShowNativeAdsResult') {
              this.tracker.trackEvent('ad_reward', 0, { content_id: contentId });
              resolve(true);
            }
          });
        });
      }
    }

    return false;
  }

  private async showMonetizationChoice(): Promise<'payment' | 'ads' | 'cancel'> {
    // Show UI choice to user
    return new Promise((resolve) => {
      const modal = document.createElement('div');
      modal.innerHTML = `
        <div class="monetization-modal">
          <h3>Unlock Premium Content</h3>
          <button id="pay-button">Pay 50₽</button>
          <button id="ads-button">Watch Ad</button>
          <button id="cancel-button">Cancel</button>
        </div>
      `;
      
      document.body.appendChild(modal);
      
      modal.querySelector('#pay-button')?.addEventListener('click', () => {
        document.body.removeChild(modal);
        resolve('payment');
      });
      
      modal.querySelector('#ads-button')?.addEventListener('click', () => {
        document.body.removeChild(modal);
        resolve('ads');
      });
      
      modal.querySelector('#cancel-button')?.addEventListener('click', () => {
        document.body.removeChild(modal);
        resolve('cancel');
      });
    });
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-vkontakte--vk-bridge

docs

advertising-monetization.md

application-lifecycle.md

authentication.md

core-bridge.md

device-features.md

geolocation.md

index.md

launch-parameters.md

middleware.md

payments-commerce.md

qr-barcode-scanning.md

social-features.md

storage-data.md

ui-display.md

user-data.md

tile.json