Skip to content
This repository has been archived by the owner on May 21, 2019. It is now read-only.

Fix FunctionCallTag registering in iOS and support to manually refreshing the container #316

Merged
merged 13 commits into from
Mar 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ local.properties
node_modules
*.log
.nvm
package-lock.json

# OS X
.DS_Store
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ GoogleTagManager.registerFunctionCallTagHandler(
// functionName is passed for convenience. In this example it will be equal to "some_function".
// tagArguments is an object and is populated based on Tag configuration in TagManager interface.
console.log("Handling Function Call tag:", functionName);
}
}
)
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ public void onResult(ContainerHolder containerHolder) {
}, 2000, TimeUnit.MILLISECONDS);
}

@ReactMethod
public void refreshContainer(final Promise promise){
if (mContainerHolder != null && mContainerHolder.getContainer() != null) {
mContainerHolder.refresh();
promise.resolve(true);
} else {
promise.reject(E_CONTAINER_NOT_OPENED, new Throwable("The container has not been opened. You must call openContainerWithId(..)"));
}
}

@ReactMethod
public void booleanForKey(final String key, final Promise promise){
if (mContainerHolder != null && mContainerHolder.getContainer() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ @implementation RCTGoogleTagManagerBridge
notifier:self];
}

RCT_REMAP_METHOD(refreshContainer,
refreshContainerWithResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
if (self.container != nil) {
[self.container refresh];
resolve(@YES);
} else {
reject(E_CONTAINER_NOT_OPENED, nil, RCTErrorWithMessage(@"The container has not been opened. You must call openContainerWithId(..)"));
}
}

RCT_EXPORT_METHOD(stringForKey:(NSString *)key
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
Expand Down Expand Up @@ -123,8 +135,10 @@ @implementation RCTGoogleTagManagerBridge
- (void)containerAvailable:(TAGContainer *)container {
dispatch_async(_methodQueue, ^{
self.container = container;
self.openContainerResolver(@YES);
self.openContainerResolver = nil;
if (self.openContainerResolver) {
self.openContainerResolver(@YES);
self.openContainerResolver = nil;
}
});
}

Expand Down
12 changes: 12 additions & 0 deletions src/GoogleTagManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ class GoogleTagManager {
return TagManagerBridge.openContainerWithId(containerId);
}

/**
* Refreshes the GTM container.
* According to Tag Manager documentations for Android can be called once every 15 minutes.
* No such limitations has been mentioned for iOS containers, though.
* @example
* GoogleTagManager.refreshContainer().then((..) => ..)
* @returns {Promise<boolean>}
*/
static refreshContainer(): Promise<boolean> {
return TagManagerBridge.refreshContainer();
}

/**
* Retrieves a boolean value with the given key from the opened container.
* @example GoogleTagManager.boolForKey("key").then(val => console.log(val));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ export default (functionName: string, handler: Handler): Promise<boolean> => {
return TagManagerBridge.registerFunctionCallTagHandler(functionName).then(
() => {
DeviceEventEmitter.addListener(event, payload => {
handler(functionName, payload);
try {
handler(functionName, payload);
} catch (e) {
console.error(
`Unhandled exception in FunctionCallTag handler: ${e.stack}`,
`\nFunction Name: ${functionName}`,
`\nPayload: ${JSON.stringify(payload)}`
);
}
});
return true;
}
Expand Down
14 changes: 9 additions & 5 deletions src/Helpers/FunctionCallTagHandler/FunctionCallTagHandlerIOS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ const functionCallTagEventEmitter = new NativeEventEmitter(TagManagerBridge);
const listeners: Array<Listener> = [];
let listenerRegistered = false;

// tagEventEmmiter is used to handle callbacks in JS
let jsEventEmitter;

export default (functionName: string, handler: Handler): Promise<boolean> => {
if (!listenerRegistered) {
// Register a global listener for Function Tag events
Expand All @@ -33,10 +30,17 @@ export default (functionName: string, handler: Handler): Promise<boolean> => {
({ _fn, payload }) => {
// Pass on the event to listeners
// _fn is basically the same as functionName
jsEventEmitter.emit(_fn, payload);
listeners.forEach(listener => {
if (listener.functionName === _fn) {
handler(_fn, payload);
try {
handler(_fn, payload);
} catch (e) {
console.error(
`Unhandled exception in FunctionCallTag handler: ${e.stack}`,
`\nFunction Name: ${_fn}`,
`\nPayload: ${JSON.stringify(payload)}`
);
}
}
});
}
Expand Down
1 change: 1 addition & 0 deletions src/NativeBridges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export interface IGoogleAnalyticsBridge {

export interface IGoogleTagManagerBridge extends EventSubscriptionVendor {
openContainerWithId(containerId: string): Promise<boolean>;
refreshContainer(): Promise<boolean>;
booleanForKey(key: string): Promise<boolean>;
stringForKey(key: string): Promise<string>;
doubleForKey(key: any): Promise<number>;
Expand Down