How to get vastAdsRequest response no ad or error from CAF SDK (Custom Web Receiver) - google-cast

I am trying to implement CAF Receiver with VAST-ad (https://developers.google.com/cast/codelabs/cast-ads-receiver#0)
I am follow codelab to implement ad break like below
const addVASTBreaksToMedia = (mediaInformation) => {
mediaInformation.breakClips = [
{
id: "bc1",
title: "bc1 (Pre-roll)",
vastAdsRequest: {
adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&url=&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&vad_type=linear&vpos=preroll&pod=1&ppos=1&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6256&correlator=' + Math.floor(Math.random() * Math.pow(10, 10)) + '&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0'
}
}
];
mediaInformation.breaks = [
{
id: "b1",
breakClipIds: ["bc1"],
position: 0
}
];
};
it works fine but our product requirement is fill content video AD when VAST response no ad or error, I need to known what vast error is.
I also trying to setBreakClipLoadInterceptor to override vast request like below
breakManager.setBreakClipLoadInterceptor((breakClip, breakCtx) => {
return new Promise((resolve, reject) =>{
let vastTagURL = breakClip.vastAdsRequest.adTagUrl;
vastParser.getAndParseVAST(vastTagURL)
.then(res => {
//override breakClip to following json structure
// {
// "id": "GENERATED:2",
// "contentId": "https://gcdn.2mdn.net/videoplayback/id/6dcf9cb098b00e2a/itag/345/source/web_video_ads/ctier/L/acao/yes/ip/0.0.0.0/ipbits/0/expire/3799888688/sparams/id,itag,source,ctier,acao,ip,ipbits,expire/signature/3886F1E3CD0868EA9D14854C95CA573BFDA9394B.3A7619FC1FD197F7B602D87CCC934C6F45885619/key/ck2/file/file.mp4",
// "contentType": "video/mp4",
// "title": "In-Stream Video",
// "duration": 15,
// "clickThroughUrl": "https://adclick.g.doubleclick.net/pcs/click?xai=AKAOjst8f8EvhlvKZ1q8-dX2BXNbH0H6hCZkVuyif5ivJncC-8sWDlA5ri4c3CPXH-eZY-ScSfDmyhF740_X0vjH0_jyn2JJVrJA4YouVsjig4Rf4ccvmSyv&sig=Cg0ArKJSzJyL3C23DvhmEAE&cry=1&fbs_aeid=[gw_fbsaeid]&urlfix=1&adurl=https://www.intel.com.tw/content/www/tw/zh/now/laptops-evolved.html%3Fcid%3Ddiad%26source%3Dgcm%26campid%3D28126613%26sid%3D5134578%26plid%3D340690077%26aid%3D532457414%26crid%3D174775371%26dclid%3D%25edclid!"
// }
resolve(breakClip);
}).catch(err => {
// fill content ad
reject()
});
});
but default interceptor will not request vast tracking pixel. (it was expected and I don't want to implement VAST tracking myself...)
breakManager.setVastTrackingInterceptor(function(vast){
// no callback when override BreakClipLoadInterceptor
});
Does someone knows how to get VAST error from CAF SDK without override breakClipsLoader?

Related

Multiple REACT API calls vs handling it all in NodeJS

I am currently using AWS DynamoDB for the backend and REACT for the frontend with a NodeJS/AWS Lambda frame.
What I'm trying to do:
Get the information of the teammates in a dataset from a teams table that contains a list of the partition keys of the profiles table, and the name of the team set as the sort key, to get their specific information for that team. I then need to get each of the teammate's universal information that is true across all teams, namely their name and profile picture.
I have 2 options:
Either loop through the list of partition keys in the team dataset that was fetched in REACT, and make a couple of API calls to retrieve their specific information, then a couple more for their universal information.
Or, I was wondering if I can instead then implement the same logic, but instead of the API calls, it will be DynamoDB querying in the Lambda function, then collect them all into a JSON object for it to be fetched by the REACT in one swoop.
Would it be a better idea? Or am I simply doing the REACT logic wrong? I am relatively new to REACT so it's definitely possible and am open to tips.
For reference, here's the code:
useEffect(() => {
let theTeammates : (userProfileResponse | undefined)[] = teammateObjects;
(async () => {
let teammatesPromises : any[] = [];
// teammates = the list of partition keys
for (let i = 0; i < teammates.length; i++) {
if(teammates[i] !== '') {
teammatesPromises.push(getSpecificUser(teammates[i], teamName))
}
}
await Promise.all(teammatesPromises)
.then((resolved) => {
if(resolved) {
theTeammates = resolved.map( (theTeammate) => {
if(theTeammate) {
let user: userProfileResponse = {
userKey: theTeammate.userKey,
teamKey: theTeammate.teamKey,
description: theTeammate.description,
userName: theTeammate.userName,
profilePic: defaultProfile,
isAdmin: theTeammate.isAdmin,
role: theTeammate.role,
}
return user as userProfileResponse;
}
})
}
})
setTeammateObjects(theTeammates as userProfileResponse[]);
}) ();
}, [teamData]);
useEffect(() => {
if(teammateObjects) {
(async () => {
let Teammates : any[] = teammateObjects.filter(x => x !== undefined)
Teammates = Teammates.map( (aTeammate) => {
getProfilePicAndName(aTeammate.userKey).then((profile) => {
if(profile) {
aTeammate.userName = profile.userName;
if(profile.profilePic !== undefined && profile.profilePic !== 'none') {
getProfilePic(profile.profilePic).then((picture) => {
if(picture) {
aTeammate.profilePic = picture
return aTeammate
}
})
} else
return aTeammate
}
})
})
}) ();
}
}, [teammateObjects])
I am currently trying to do it through the react. It works for the most part, but I have noticed that sometimes some of the API calls fail, and some of the teammates don't get fetched successfully and never get displayed to the user until the page is refreshed, which is not acceptable.

Push notification shows object Object even though i am setting the right value

I am trying to implement push notifications with react and nodejs using service workers.
I am having problem while i am showing notification to the user.
Here is my service worker code:
self.addEventListener('push', async (event) => {
const {
type,
title,
body,
data: { redirectUrl },
} = event.data.json()
if (type === 'NEW_MESSAGE') {
try {
// Get all opened windows that service worker controls.
event.waitUntil(
self.clients.matchAll().then((clients) => {
// Get windows matching the url of the message's coming address.
const filteredClients = clients.filter((client) => client.url.includes(redirectUrl))
// If user's not on the same window as the message's coming address or if it window exists but it's, hidden send notification.
if (
filteredClients.length === 0 ||
(filteredClients.length > 0 &&
filteredClients.every((client) => client.visibilityState === 'hidden'))
) {
self.registration.showNotification({
title,
options: { body },
})
}
}),
)
} catch (error) {
console.error('Error while fetching clients:', error.message)
}
}
})
self.addEventListener('notificationclick', (event) => {
event.notification.close()
console.log(event)
if (event.action === 'NEW_MESSAGE') {
event.waitUntil(
self.clients.matchAll().then((clients) => {
if (clients.openWindow) {
clients
.openWindow(event.notification.data.redirectUrl)
.then((client) => (client ? client.focus() : null))
}
}),
)
}
})
When new notification comes from backend with a type of 'NEW_MESSAGE', i get the right values out of e.data and try to use them on showNotification function but it seems like something is not working out properly because notification looks like this even though event.data equals to this => type = 'NEW_MESSAGE', title: 'New Message', body: , data: { redirectUrl: }
Here is how notification looks:
Thanks for your help in advance.
The problem was i assigned parameters in the wrong way.
It should've been like this:
self.registration.showNotification(title, { body })

How to create new item in Nodejs?

Have a simply issue. Currently doing some pet-project and took nodejs api for it.
The API is written on nodejs and want to implements with my react-app.
But bumped into i can not create dummy date and to try testing the ui.
Here is method of creating:
.post('/', function (req, res) {
var directory = _.pick(req.body, [
'parentId',
'name'
]
)
, parent = _.find(store.directories, function (dir) {
return dir.id == directory.parentId
})
if (parent) {
_.assign(directory, { id: idGenerator.getNext() })
store.directories.push(directory)
res.send(directory)
} else {
res.status(500).send('no parent')
}
})
The problem is i can not even to make a new row in postman:
{
"parentId": 1,
"name": "some title"
}
Sending RAW => json and receiving: "Cannot POST /"

create theme on shopify using api

I am trying to create an app and within the app the user can install a theme, however, I can't seem to work out why the theme is not being created. It keeps pulling the themes already installed on my store to the console, my code doesn't seem to create a theme that would show up on my shopify store.
server.js
router.post('/api/theme', async (ctx) => {
try {
const results = await fetch("https://" + ctx.cookies.get('shopOrigin') + "/admin/themes.json", {
headers: {
'X-Shopify-Access-Token': ctx.cookies.get('accessToken')
},
})
.then(response => response.json())
.then(json => {
console.log("https://" + ctx.cookies.get('shopOrigin') + "/admin/api/2020-01/themes.json", json);
});
ctx.body = {
data: results
};
} catch (err) {
console.log(err)
}
});
frontend .js file
async function getUser() {
var url = `/api/theme`;
var method = 'post';
const theme = {
theme: {
name: "Lemongrass",
src: "https://codeload.github.com/Shopify/skeleton-theme/zip/master"
}
};
const data = JSON.stringify(theme);
fetch(url, { method: method, body: data})
}
In order to create a theme you need a zip archive of the theme you like to create.
The end point should be /admin/api/2020-01/themes.json and the body should be something like this:
{
"theme": {
"name": "Theme name",
"src": "http://themes.shopify.com/theme.zip",
"role": "unpublished"
}
}
Please refer to https://shopify.dev/docs/admin-api/rest/reference/online-store/theme#create-2020-01 for more information.
At the moment from your code I don't see neither the correct POST request, neither the archive file.

Cloud Functions for Firebase: Not sending notification to all users

I have created an e-commerce Android app with Firebase and a Flutter app to update the Firebase nodes.
I want to send a notification to all users whenever the admin updates the exchange rate.
Below is the code I wrote to send the update notification to all registered tokens using a Cloud Function but it only sends the notification to the Flutter app instead of both apps.
I don't know what I am doing wrong.
Here is my functions code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.helloWorld=functions.database.ref('Rates').onUpdate(evt =>{
const payload={
notification:{
title:"Today's Rate",
body :"Click here to see today's gold rate",
badge: '1',
sound: 'default'
}
}
return admin.database().ref('fcm-token').once('value').then(allToken =>{
if(allToken.val()){
console.log('token available');
const token = Object.keys(allToken.val());
console.log(admin.messaging().sendToDevice(token, payload));
return admin.messaging().sendToDevice(token, payload);
}else{
console.log('No Token Available');
throw new Error("Profile doesn't exist")
}
});
});
This is an image of my Realtime Database Structure.
Based on your provided screenshot of your database, the data below /fcm-token in your database has two different formats.
When you added the data manually, you used the format:
{
"fcm-token": {
"someRegistrationToken": {
"token": "someRegistrationToken"
},
"someOtherRegistrationToken": {
"token": "someOtherRegistrationToken"
}
...
},
...
}
Whereas, from your "auto registered" entries, you added the tokens using:
{
"fcm-token": {
"somePushId": {
"fcmToken": "someRegistrationToken"
},
"someOtherPushId": {
"fcmToken": "someOtherRegistrationToken"
},
...
},
...
}
In your Cloud Functions code, you collect all the keys stored under /fcm-token into an array using Object.keys(allToken.val()) which will give you an array containing a mix of push IDs and FCM tokens which is not what you want and is why some devices are missing notifications.
So in short, decide on one format or the other.
Temporary work-around
With your existing mixed structure, you can use the following that will ignore what you use as the key and only extracts the token:
return admin.database().ref('fcm-token').once('value').then(allTokensSnapshot => {
if (allTokensSnapshot.exists()) {
console.log('Tokens available');
const tokenArray = [];
allTokensSnapshot.forEach((tokenSnapshot) => {
let token = tokenSnapshot.hasChild('fcmToken')
? tokenSnapshot.child('fcmToken').val()
: tokenSnapshot.child('token').val();
tokenArray.push(token);
});
return admin.messaging().sendToDevice(tokenArray, payload);
} else {
console.log('No tokens available');
throw new Error('No tokens available');
}
});
Database flattening
Personally, I'd flatten it out so you can use your code as-is, but this would require changing the way you add tokens to the database:
Database structure:
{
"fcm-token": {
"someRegistrationToken": true,
"someOtherRegistrationToken": true,
...
}
}
(You could also use the device owner's user ID instead of true if desired)
Client code:
FirebaseInstanceId.getInstance().getInstanceId()
.addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult result) {
DatabaseReference allTokensRef = FirebaseDatabase.getInstance().getReference().child("fcm-token");
String token = result.getToken();
Log.e("Test", "FCM Registration Token: " + token);
SharedPreferences preferences = this.getSharedPreferences("com.jk.jkjwellers", MODE_PRIVATE);
if(!(preferences.getBoolean("FCMAdded", false))){
allTokensRef.child(token).setValue(true);
preferences.edit().putBoolean("FCMAdded",true).apply();
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e("Test", "Failed to get FCM registration token", e);
}
});
Not sure, but try replacing
databaseReference.push().setValue(new Tokens(token));
with
databaseReference.child(token).setValue(new Tokens(token));

Resources