Skip to main content

Setting up a JavaScript Playable for Luna Playground

Luna Playground offers support for JavaScript playables, created outside of the Luna plugin. You can benefit from all of the features such as playable variations, multi-ad network support and playable ad analytics.

This guide outlines the steps necessary to adapt your JavaScript playable ad for us with Luna Playground.

Before continuing with the steps on this page please be sure to have downloaded your HTML5 playable from your provider, or as an export from the game engine being used.

Please note that these steps are also detailed on our community github alongside 2 example folders containing ready-to-upload playables.

Step by step#

1. Make sure your html file is named "source.html"#

WARNING! Luna will not apply further compression or obfuscation once you have uploaded your files. Please minify and obfuscate your playables prior to uploading.

2. Make sure all the startup functionality is performed in the startGame() function#

3. Create 2 json files#

The name of these files needs to be luna.json and the other playground.json, these will be necessary for uploading to Playground.

4. Populate your playground.json#

Within your playground.json you will need to create a new object with 2 fields; "title" & "icon", and another object within it called "fields".
Example of how this should look below:

{
"title": "Basic Playable",
"icon": "", // Icon next to the playable in Luna Playground, takes a Data URL.
"fields": {} // You can populate this with any settings you wish to be editable in Playground
}

If you would like an example of how to populate the fields object for Playground click here.

5. Within your luna.json add the following:#

{
"unity": {
"packages": {
"default": {
"applicationName": "",
"iosLink": "",
"androidLink": "",
"orientation": "unspecified",
"supportedLanguages": [
"en"
]
},
"ironsource": {
"appID": "",
"assetID": "",
"applicationGenre": "",
"versionName": "",
"apiType": 0,
"playableMode": 0,
"packageType": 0
},
"facebook": {
"assetID": "",
"packageType": 0
},
"tiktok": {
"orientation": 0
}
}
}
}

To learn about what should be entered in each field in your luna.json click here.

6. Add callback events to your playable#

For example:

// Subscribe to luna:build event – will be fired right after 'load' event of the window.
window.addEventListener( "luna:build", function() {
log( 'Playable is about to start' );
} );

You can see a list of our callback events by clicking here.

7. Use the Luna API to direct the user to the app store#

The API call needed: Luna.Unity.Playable.InstallFullGame()

8. Extra step if you wish to run on Mintegral or Vungle#

If you wish to run on Mintegral or Vungle, please also call the Luna.Unity.LifeCycle.GameEnded() event when the game is complete.

9. Zip your playable & json files#

The last step is to zip your 3 files (source.html, luna.json, playground.json). Then drag and drop the resulting zip at the bottom of the playground.lunalabs.io/apps page. (You can also click on the browse text at the bottom of the page, navigate to where the zip is in the opened window and hit open).

images-small

Optional Extra Steps#

  1. Update your luna.json file with your app store URLs. (Click here to learn about what to put in each field)
  2. Update your playground.json file with parameters in your game, for quick editing in Playground.
  3. Use Luna Custom Events. (see below)

Custom Events#

It is possible to use the Luna Analytics events API for custom events in your playable. Please see here for full documentation of the API, and here for information on Events Settings.

Implementation Example:

window.pi.logCustomEvent("LevelFailed", 1);
window.pi.logCustomEvent("EndCardShown");

luna.json guide#

Click the arrow below to see a table comprising all you need to know regarding each field in the luna.json file.

CLICK ME
SectionField NameData TypeDescription
defaultapplicationNameStringYour playable's name
defaultiosLinkStringYour iOS App Store link
defaultandroidLinkStringYour Android App Store link
defaultorientationStringCan be one of: "unspecified", "portrait" or "landscape"
defaultsupportedLanguagesArray of StringsList the languages your playable supports via listing the corresponding language codes (formatted like this: "en", "fr", ...)
ironsourceappIDStringOptional
ironsourceassetIDStringOptional
ironsourceapplicationGenreStringOptional
ironsourceversionNameStringOptional
ironsourceapiTypeintEnter either 0 or 1: 0 for DAPI, 1 for NUCLEO
ironsourceplayableModeintEnter either 0 or 1: 0 for PA, 1 for IEC
ironsourcepackageTypeintEnter either 0 or 1: 0 for Inline, 1 for CDN
facebookassetIDStringOptional
facebookpackageTypeintEnter either 0 or 1: 0 if your are submitting using a ZIP file (5Mb limit), or 1 for a single inlined HTML file (2Mb limit)
tiktokorientationintEnter 0, 1 or 2: 0 for "responsive", 1 for "portrait" or 2 for "landscape"

Fields example#

Click the arrow below to view an example of how to populate the fields object for Playground.

CLICK ME
"fields": {
"ShapeController": {
"shapeColor": {
"title": "shapeColor",
"type": "color",
"defaultValue": [
1,
0,
0,
1
],
"section": "",
"order": 1,
"localization": 0,
"options": {}
},
"shape": {
"title": "shape",
"type": "enum",
"defaultValue": 1,
"section": "",
"order": 2,
"localization": 0,
"options": {
"0": "CUBE",
"1": "SPHERE",
"2": "CYLINDER"
}
},
"someBoolean": {
"title": "someBoolean",
"type": "boolean",
"defaultValue": 1,
"section": "",
"order": 3,
"localization": 0,
"options": {}
},
"someInt": {
"title": "someInt",
"type": "int32",
"defaultValue": 100,
"section": "",
"order": 4,
"localization": 0,
"options": {}
},
"someVector3": {
"title": "someVector3",
"type": "vector3",
"defaultValue": [
0,
1,
0
],
"section": "",
"order": 5,
"localization": 0,
"options": {}
},
"someString": {
"title": "someString",
"type": "string",
"defaultValue": [
"This is a string"
],
"section": "",
"order": 6,
"localization": 0,
"options": {}
},
"mySlider":{
"title": "mySlider",
"type": "int32",
"defaultValue": 10,
"constraints": {
"value_min":1,
"value_max":15,
"value_step":1
}
},
"myVec3Array":{
"title": "myVec3Array",
"type": "vector3[]",
"defaultValue": [
[2,4,6], [1,3,5]
],
"constraints": {
"array_min_length":0,
"array_max_length":3
}
}
}
},
}

Callback Events#

A list of the callback events available

// Subscribing to luna:build event – it is going to be fired right after 'load' event of the window.
window.addEventListener( "luna:build", function() {
log( 'Playable is about to start' );
} );
// Subscribing to luna:unmute event – the playable can play sounds once it is fired.
window.addEventListener( "luna:unmute", function() {
log( 'Playable needs to be unmuted' );
} );
// Subscribing to luna:mute event – the playable must mute all the sounds once it is fired.
window.addEventListener( "luna:mute", function() {
log( 'Playable needs to be muted' );
} );
// Subscribing to luna:pause event – the playable must pause rendering and sound playaback.
window.addEventListener( 'luna:pause', function () {
log( 'Playable needs to be paused' );
} );
// Subscribing to luna:pause event – the playable must resume rendering and sound playaback.
window.addEventListener( 'luna:resume', function () {
log( 'Playable needs to be resumed' );
} );
// check if Luna is defined in global namespace
if ( 'Luna' in window ) {
// it is - nothing to do, the startGame() will be invoked when needed
log( 'window.Luna is set - startGame() will be called automatically' );
} else {
// it is not - probably a development build, invoke startGame() manually
startGame();
}