npm version Downloads DeepScan grade License
The Ultimate Build Tool for HTML5 Playable Ads
@smoud/playable-scripts is a powerful CLI and API tool designed to streamline the development, optimization, and packaging of HTML5 playable ads for multiple ad networks. Whether you're building playables for Google Ads, Meta (Facebook), AppLovin, Unity, IronSource, Vungle, Mintegral, and more, this tool provides a one-command solution to handle network-specific requirements, asset optimization, and build automation.
- 🚀 One-Command Build Process – Easily generate builds for different ad networks.
- ⚡ Automatic Optimizations – Includes minification, tree-shaking, and dead code elimination.
- 🎯 Pre-configured for Major Ad Networks – Works out of the box with Google Ads, Meta (Facebook), AppLovin, Unity, IronSource, Vungle, Mintegral, and many more.
- 🛠️ Customizable – Extend the default build pipeline as needed.
npm install --save-dev @smoud/playable-scripts
- Install the package
- Create a basic project structure:
your-playable/
├── src/
│ ├── index.html
│ └── index.ts
├── package.json
└── build.json (optional)
- Add scripts to your package.json:
{
"scripts": {
"dev": "playable-scripts dev",
"build": "playable-scripts build"
}
}- Start development:
npm run dev
- Build for google:
npm run build google
While @smoud/playable-scripts handles the build process, you'll need additional functionality to make your playable ads fully compatible across different ad networks. This is where @smoud/playable-sdk comes in.
@smoud/playable-sdk is a powerful, unified SDK that:
- 🔄 Seamlessly integrates with multiple ad network SDKs (MRAID, Google, Facebook, Vungle, etc.)
- 🎯 Provides a standardized interface for all networks
- 🚀 Ensures cross-platform compatibility and optimization
- 🛠️ Handles ad network-specific requirements automatically
- 💪 Lets you focus on creating engaging interactive ads
npm install @smoud/playable-sdk
import { sdk } from '@smoud/playable-sdk'; // Initialize SDK with container dimensions sdk.init((width, height) => { new Game(width, height); });
sdk.on('resize', game.resize, game); sdk.on('pause', game.pause, game); sdk.on('resume', game.resume, game); sdk.on('volume', game.volume, game); sdk.on('finish', game.finish, game);
// Mark as resources loaded and gameplay started sdk.start(); // Mark as complete sdk.finish(); // Handle CTA clicks installButton.onclick = () => sdk.install();
If you choose not to use @smoud/playable-sdk, you'll need to:
- Implement network-specific requirements manually
- Handle compatibility issues across different platforms
- Manage SDK integrations individually
For detailed implementation guidelines, visit our GitHub repository.
| Option | Description | Default | Example |
|---|---|---|---|
| Ad Network | Target ad network | preview |
applovin |
--out-dir |
Output directory template for build files | dist |
--out-dir build/{version} |
--build-config |
Path to build.json configuration file | build.json |
--build-config custom.json |
--ts-config |
Path to tsconfig.json configuration file | tsconfig.json |
--ts-config tsconfig.prod.json |
--js-config |
Path to jsconfig.json configuration file | jsconfig.json |
--js-config jsconfig.prod.json |
--protocol |
Ad protocol to use | none |
--protocol mraid |
--zip |
ZIP output result | false |
--zip |
--port |
Development server port number | 3000 |
--port 8080 |
--open |
Open browser automatically | false |
--open |
--dev |
Enable development mode | true for devfalse for build |
--dev false |
--filename |
Template for output filename | See Build Configuration | --filename {app}-{version} |
--app |
Application name | See Build Configuration | --app MyGame |
--name |
Concept name | See Build Configuration | --name Concept1 |
--version |
Build version | See Build Configuration | --version v2.1 |
--language |
Language code | See Build Configuration | --language fr |
--orientation |
Orientation identifier | See Build Configuration | --orientation portrait |
--skip-recommended-meta |
Skip recommended meta tags injection | - | --skip-recommended-meta |
--drop-console |
Drop console logging on production | true |
--drop-console false |
--debugger |
URL of debugger script to inject | - | --debugger http://... |
Specify the target network directly as a command argument:
playable-scripts build unity
preview(Preview) - Browser previewapplovin(AL) - AppLovinunity(UNITY) - Unity Adsgoogle(GOOGLE) - Google Adsironsource(IS) - ironSourcefacebook(FB) - Facebookmoloco(MOLOCO) - Molocoadcolony(ADCOLONY) - AdColonymintegral(MINTEGRAL) - Mintegralvungle(VUNGLE) - Vungletapjoy(TAPJOY) - Tapjoysnapchat(SNAPCHAT) - Snapchattiktok(TIKTOK) - TikTok / Toutiaoappreciate(APPRECIATE) - Appreciatechartboost(CHARTBOOST) - Chartboostpangle(PANGLE) - Panglemytarget(MYTARGET) - MyTargetliftoff(LIFTOFF) - Liftoffsmadex(SMADEX) - Smadexadikteev(ADIKTEEV) - Adikteevbigabid(BIGABID) - Bigabidinmobi(INMOBI) - inMobi
none- No specific ad protocolmraid- Mobile Rich Media Ad Interface Definitionsdapi- Display Advertising Programming Interface
Note: MRAID protocol is automatically used for ironSource, AppLovin, Unity, Appreciate, Snapchat, Chartboost, MyTarget, Liftoff, Adikteev, Bigabid, inMobi and AdColony networks.
The build.json file allows you to customize build options. Here's the format:
{
"filename": "{app}_{name}_{version}_{date}_{language}_{network}",
"app": "AppName",
"name": "ConceptName",
"version": "v1",
"language": "en",
"googlePlayUrl": "https://play.google.com/store/games",
"appStoreUrl": "https://www.apple.com/app-store/"
}All fields are optional and will use the default values shown here if not specified.
Check Default options to see full list of available options.
The outDir and filename templates supports the following variables:
{app}- Application name{name}- Concept name{version}- Build version{date}- Current date{language}- Language code{orientation}- Orientation identifier{network}- Target ad network{hash}- Unique build identifier
The following global defines are automatically available in your code during development and build:
| Define | Description | Example Value |
|---|---|---|
__DEV__ |
Boolean flag indicating development mode | true or false |
GOOGLE_PLAY_URL |
Google Play Store URL constant | "https://play.google.com/store/" |
APP_STORE_URL |
App Store URL constant | "https://www.apple.com/app-store/" |
AD_NETWORK |
Current advertising network identifier | "google", "facebook", etc. |
AD_PROTOCOL |
Current advertising protocol | "none", "mraid", "dapi" |
APP |
Application name constant | "AppName" |
NAME |
Build name constant | "ConceptName" |
VERSION |
Build version constant | "v1" |
LANGUAGE |
Current language code | "en", "es", etc. |
ORIENTATION |
Current orientation identifier | "both", "portrait", etc. |
BUILD_HASH |
Unique build hash | "a1b2c3d4" |
These defines can be used in your code for conditional logic:
if (__DEV__) { console.log('Dev mode is active'); } if (AD_NETWORK === 'google') { // google network specific code } console.log(`Current language: ${LANGUAGE}`);
You can also add custom defines by modifying the defines property in your build.json file:
{
"defines": {
"CUSTOM_DEFINE": "'custom value'",
"FEATURE_FLAG": "true"
}
}@smoud/playable-scripts automatically manages viewport meta tags for optimal display across devices.
Do not specify your own viewport meta tag as it will be handled and injected into your HTML automatically:
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover,maximum-scale=1.0,user-scalable=no">
For Mintegral network, a special viewport configuration is used:
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
Additionally, unless --skip-recommended-meta is provided, the following recommended meta tags are automatically injected:
<meta name="HandheldFriendly" content="True" /> <meta name="cleartype" http-equiv="cleartype" content="on" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" /> <meta http-equiv="X-UA-Compatible" content="IE=10" />
Start development server:
playable-scripts dev --port 3000 --open
Build for AppLovin:
npx playable-scripts build applovin
npm run build applovin
Build with DAPI protocol with specific version:
npx playable-scripts build ironsource --protocol dapi --version endcard_2
npm run build ironsource -- --protocol dapi --version endcard_2
The package provides a programmatic API for integration into your build tools:
const options = { outDir: 'dist', // Output directory for build files buildConfig: 'build.json', // Path to build.json configuration file tsConfig: 'tsconfig.json', // For TypeScript projects, path to tsconfig.json file jsConfig: 'jsconfig.json', // For JavaScript projects, path to jsconfig.json file port: 3000, // Development server port number open: false, // Whether to open browser automatically protocol: 'none', // Ad protocol to use (none, mraid, or dapi) network: 'preview', // Target Ad network zip: false, // Should the build be zipped? Works only for Ad networks which allows both .zip and .html filename: '{app}_{name}_{version}_{date}_{language}_{network}', // Template for output filename app: 'AppName', // Application name used in build filename and APP define name: 'ConceptName', // Concept name used in build filename and NAME define version: 'v1', // Version name used in build filename and VERSION define language: 'en', // Language code for localization orientation: 'both', // Orientation identifier. Adaptive design, which supports both orientations - is preferred googlePlayUrl: 'https://play.google.com/store/games', // Google Play Store URL appStoreUrl: 'https://www.apple.com/app-store/', // App Store URL dev: undefined, // Development mode flag skipRecommendedMeta: undefined, // Skip recommended meta tags injection debugger: undefined, // URL of debugger script to inject defines: {}, // Defines options compilation: { // Compilation options allowTemplateLiterals: true, // Enable or disable template literals in the build dropConsole: true // Drop console.log, console.warn, and console.info for a production build }, adNetworkNames: { // Mapping of ad network identifiers to their display names in filenames preview: 'Preview', applovin: 'AL', unity: 'UNITY', google: 'GOOGLE', ironsource: 'IS', facebook: 'FB', moloco: 'MOLOCO', adcolony: 'ADCOLONY', mintegral: 'MINTEGRAL', vungle: 'VUNGLE', tapjoy: 'TAPJOY', snapchat: 'SNAPCHAT', tiktok: 'TIKTOK', appreciate: 'APPRECIATE', chartboost: 'CHARTBOOST', pangle: 'PANGLE', mytarget: 'MYTARGET', liftoff: 'LIFTOFF', smadex: 'SMADEX', adikteev: 'ADIKTEEV', bigabid: 'BIGABID', inmobi: 'INMOBI' } };
const { options, mergeOptions, parseArgvOptions } = require('@smoud/playable-scripts'); // Merge custom options with defaults const customOptions = mergeOptions(options, { outDir: 'custom-dist', network: 'applovin' }); // Parse CLI arguments const newOptions = parseArgvOptions([ { name: 'custom-option', hasValue: true, defaultValue: 'default' } ]); // Change build options newOptions.app = 'Example'; newOptions.version = 'v4'; // Change defines options newOptions.defines = { APP_STORE_URL: JSON.stringify('https://www.apple.com/app-store/'); __DEV__: JSON.stringify(false); } // Merge new options with defaults const finalOptions = mergeOptions(options, newOptions);
const { makeWebpackDevConfig, makeWebpackBuildConfig } = require('@smoud/playable-scripts'); const { webpackCommonConfig } = require('@smoud/playable-scripts'); const { merge } = require('webpack-merge'); // Create development configuration const devConfig = makeWebpackDevConfig(customOptions); // Create production configuration const buildConfig = makeWebpackBuildConfig(); // Create production configuration with custom definitions const buildConfig2 = makeWebpackBuildConfig(customOptions, customDefinitions); // Create production configuration with custom definitions and custom webpack config to merge const buildConfig3 = makeWebpackBuildConfig(customOptions, customDefinitions, customWebpackConfig); // Create your own webpack config, based on webpackCommonConfig const customConfig = merge(webpackCommonConfig, { // ... });
const { runDev } = require('@smoud/playable-scripts'); // Start development server with custom config runDev(webpackDevConfig); // Start development server with default config runDev(); // Start development server with custom definitions runDev(null, null, customDefines);
const { runBuild } = require('@smoud/playable-scripts'); // Run production build with custom config runBuild(webpackBuildConfig); // Run production build with default config runBuild(); // Run production build with custom options runBuild(null, customOptions);
The package includes several webpack plugins for ad network integration:
const { ExitAPIInjectorPlugin, DebuggerInjectionPlugin } = require('@smoud/playable-scripts'); // Google Ads ExitAPI integration new ExitAPIInjectorPlugin(); // Custom debugger integration new DebuggerInjectionPlugin('http://debugger-url');
Get started quickly with our template projects:
- playable-template-base - Clean TypeScript starter with minimal dependencies
- playable-template-base-js - Clean JavaScript starter with minimal dependencies
- playable-template-pixi - PixiJS template for 2D playable ads
- playable-template-three - Three.js template for 3D playable ads
- playable-template-phaser - Phaser template for 2D playable ads
Report issues at GitHub Issues