Thanks for the info it helped me come up with an even better solution!
Heres what I mean about the block (when this.dispatchEvent is called inside a inside another function / thread)
This will log the correct data but won’t fire to the page:
connectedCallback() {
branch.init('key_live_...', function(err, data) {
if (data != null) {
const branchResult = JSON.stringify(data);
console.log(branchResult);
this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: '' + branchResult}));
}
});
}
This will also log but won’t fire to the page:
connectedCallback() {
const delayInMilliseconds = 1000;
setTimeout(function() {
console.log('1 second passed fire event');
this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: 'test data'}));
}, delayInMilliseconds);
}
I suspect that the reference to ‘this.’ is changing inside the block/thread and I can confirm it with this:
connectedCallback() {
console.log(this); // logs: <branch-io></branch-io>
const delayInMilliseconds = 1000;
setTimeout(function() {
console.log(this); // logs: Window {}
this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: 'test data'}));
}, delayInMilliseconds);
}
However I learned I can set up a promise function outside the class and the async / await syntax works (this will fire every time):
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async connectedCallback() {
await delay(1000);
console.log('Second passed fire');
this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: 'test data'}));
}
Now very strangely if I do the same for the ‘branch.init’ function it will fire in test mode, and the first live load, but not when opened from an actual link. It will log the correct data though:
function initializeBranch() {
return new Promise((resolve, reject) => {
branch.init('key_live_...', function(err, data) {
resolve(JSON.stringify(data));
});
});
}
async connectedCallback() {
const branchResult = await initializeBranch();
console.log('Result ' + branchResult);
this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: branchResult}));
}
I suspect here that maybe the ‘dispatchEvent’ is attempting to fire before the main page has finished loading and the ‘.on’ is connected so with that and the new information you gave me led to this solution:
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function initializeBranch() {
return new Promise((resolve, reject) => {
branch.init('key_live_...', function(err, data) {
resolve(JSON.stringify(data));
});
});
}
// Then inside the class
class BranchIO extends HTMLElement {
constructor() {
super();
}
async connectedCallback() {
const branchResult = await initializeBranch();
await delay(1000);
this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: branchResult}));
}
}
That will fire every time both test, live and real link opens and I think it definitely ensures that the branch init will be finished by the time the call is made. I’m very happy with that solution 
Thank you!