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

Commit 7f8a017

Browse files
fshafieecbrevik
authored andcommitted
Fix FunctionCallTag registering in iOS and support to manually refreshing the container (#316)
This PR fixes an error in `FunctionCallTagHandlerIOS.ts` module which caused the app to to crash due to a method call on an uninitialized variable. It also adds `refreshContainer` method so that developers can control the refresh rate of the contianer. @cbrevik, I did not document this method in the README file because I was not able to see it working properly. The native module was acting up and always throwing too many request error, and the new variables that we defined in the GTM console never became available, but the bridge works as expected, since these logs come form the native module not the bridge itself. If you decide to document it in the README, make note of that (per Google's own words) this method should not be called more than once per each 15 minutes.
1 parent ca88185 commit 7f8a017

8 files changed

Lines changed: 59 additions & 9 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ local.properties
3434
node_modules
3535
*.log
3636
.nvm
37+
package-lock.json
3738

3839
# OS X
3940
.DS_Store

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ GoogleTagManager.registerFunctionCallTagHandler(
112112
// functionName is passed for convenience. In this example it will be equal to "some_function".
113113
// tagArguments is an object and is populated based on Tag configuration in TagManager interface.
114114
console.log("Handling Function Call tag:", functionName);
115-
}
115+
}
116116
)
117117
```
118118

android/src/main/java/com/idehub/GoogleAnalyticsBridge/GoogleTagManagerBridge.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ public void onResult(ContainerHolder containerHolder) {
8080
}, 2000, TimeUnit.MILLISECONDS);
8181
}
8282

83+
@ReactMethod
84+
public void refreshContainer(final Promise promise){
85+
if (mContainerHolder != null && mContainerHolder.getContainer() != null) {
86+
mContainerHolder.refresh();
87+
promise.resolve(true);
88+
} else {
89+
promise.reject(E_CONTAINER_NOT_OPENED, new Throwable("The container has not been opened. You must call openContainerWithId(..)"));
90+
}
91+
}
92+
8393
@ReactMethod
8494
public void booleanForKey(final String key, final Promise promise){
8595
if (mContainerHolder != null && mContainerHolder.getContainer() != null) {

ios/RCTGoogleAnalyticsBridge/RCTGoogleAnalyticsBridge/RCTGoogleTagManagerBridge.m

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,18 @@ @implementation RCTGoogleTagManagerBridge
4747
notifier:self];
4848
}
4949

50+
RCT_REMAP_METHOD(refreshContainer,
51+
refreshContainerWithResolver:(RCTPromiseResolveBlock)resolve
52+
rejecter:(RCTPromiseRejectBlock)reject)
53+
{
54+
if (self.container != nil) {
55+
[self.container refresh];
56+
resolve(@YES);
57+
} else {
58+
reject(E_CONTAINER_NOT_OPENED, nil, RCTErrorWithMessage(@"The container has not been opened. You must call openContainerWithId(..)"));
59+
}
60+
}
61+
5062
RCT_EXPORT_METHOD(stringForKey:(NSString *)key
5163
resolver:(RCTPromiseResolveBlock)resolve
5264
rejecter:(RCTPromiseRejectBlock)reject)
@@ -123,8 +135,10 @@ @implementation RCTGoogleTagManagerBridge
123135
- (void)containerAvailable:(TAGContainer *)container {
124136
dispatch_async(_methodQueue, ^{
125137
self.container = container;
126-
self.openContainerResolver(@YES);
127-
self.openContainerResolver = nil;
138+
if (self.openContainerResolver) {
139+
self.openContainerResolver(@YES);
140+
self.openContainerResolver = nil;
141+
}
128142
});
129143
}
130144

src/GoogleTagManager.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ class GoogleTagManager {
2424
return TagManagerBridge.openContainerWithId(containerId);
2525
}
2626

27+
/**
28+
* Refreshes the GTM container.
29+
* According to Tag Manager documentations for Android can be called once every 15 minutes.
30+
* No such limitations has been mentioned for iOS containers, though.
31+
* @example
32+
* GoogleTagManager.refreshContainer().then((..) => ..)
33+
* @returns {Promise<boolean>}
34+
*/
35+
static refreshContainer(): Promise<boolean> {
36+
return TagManagerBridge.refreshContainer();
37+
}
38+
2739
/**
2840
* Retrieves a boolean value with the given key from the opened container.
2941
* @example GoogleTagManager.boolForKey("key").then(val => console.log(val));

src/Helpers/FunctionCallTagHandler/FunctionCallTagHandlerAndroid.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,15 @@ export default (functionName: string, handler: Handler): Promise<boolean> => {
1919
return TagManagerBridge.registerFunctionCallTagHandler(functionName).then(
2020
() => {
2121
DeviceEventEmitter.addListener(event, payload => {
22-
handler(functionName, payload);
22+
try {
23+
handler(functionName, payload);
24+
} catch (e) {
25+
console.error(
26+
`Unhandled exception in FunctionCallTag handler: ${e.stack}`,
27+
`\nFunction Name: ${functionName}`,
28+
`\nPayload: ${JSON.stringify(payload)}`
29+
);
30+
}
2331
});
2432
return true;
2533
}

src/Helpers/FunctionCallTagHandler/FunctionCallTagHandlerIOS.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ const functionCallTagEventEmitter = new NativeEventEmitter(TagManagerBridge);
2222
const listeners: Array<Listener> = [];
2323
let listenerRegistered = false;
2424

25-
// tagEventEmmiter is used to handle callbacks in JS
26-
let jsEventEmitter;
27-
2825
export default (functionName: string, handler: Handler): Promise<boolean> => {
2926
if (!listenerRegistered) {
3027
// Register a global listener for Function Tag events
@@ -33,10 +30,17 @@ export default (functionName: string, handler: Handler): Promise<boolean> => {
3330
({ _fn, payload }) => {
3431
// Pass on the event to listeners
3532
// _fn is basically the same as functionName
36-
jsEventEmitter.emit(_fn, payload);
3733
listeners.forEach(listener => {
3834
if (listener.functionName === _fn) {
39-
handler(_fn, payload);
35+
try {
36+
handler(_fn, payload);
37+
} catch (e) {
38+
console.error(
39+
`Unhandled exception in FunctionCallTag handler: ${e.stack}`,
40+
`\nFunction Name: ${_fn}`,
41+
`\nPayload: ${JSON.stringify(payload)}`
42+
);
43+
}
4044
}
4145
});
4246
}

src/NativeBridges.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export interface IGoogleAnalyticsBridge {
6767

6868
export interface IGoogleTagManagerBridge extends EventSubscriptionVendor {
6969
openContainerWithId(containerId: string): Promise<boolean>;
70+
refreshContainer(): Promise<boolean>;
7071
booleanForKey(key: string): Promise<boolean>;
7172
stringForKey(key: string): Promise<string>;
7273
doubleForKey(key: any): Promise<number>;

0 commit comments

Comments
 (0)