How to disable Google Tag Manager console logging

Viewed 4737

After I added Google Tag Manager to the project I see lots its log entries in the console. Is there a way to disable it? Console log is full of noise:

GoogleTagManager info: Processing logged event: _vs with parameters: {
    "_o" = auto;
    "_pc" = UIViewController;
    "_pi" = "-3988739357756819671";
    "_sc" = "Bubbie.MamboBamboViewController";
    "_si" = "-3988739357756819670";
}
2017-07-27 12:01:09.744 BubbieHuff[77205:6894827] GoogleTagManager info: Processing logged event: show_view with parameters: {
    "_sc" = "Bubbie.MamboBamboViewController";
    "_si" = "-3988739357756819670";
    name = Mambo;
}
6 Answers

After a lot of digging, I managed to find a way to disable warning and error logs (not info logs unfortunately) in Google Tag Manager v7.0.0.

Code below is written in Swift 5:

static func turnOffGTMLogs() {

        let tagClass: AnyClass? = NSClassFromString("TAGJSExportedInstructions")

        guard
            var properties = class_copyMethodList(tagClass, nil)
            else { return }

        let detourSelector = #selector(FirebaseInitializer.detour_logMessage(with:message:))
        var pointed = properties.pointee
        while(!pointed.isNil()) {
            if method_getName(pointed).coreStoreDumpString.contains("logMessage") {
                guard let detourMethod = class_getClassMethod(FirebaseInitializer.self, detourSelector) else { return }
                let _ = class_replaceMethod(tagClass, method_getName(pointed), method_getImplementation(detourMethod), method_getTypeEncoding(pointed))
                break
            }
            properties = properties.advanced(by: 1)
            pointed = properties.pointee
        }
    }

@objc
static func detour_logMessage(with level: Int, message: String) {
    return
}

Extension for opaque pointer:

private extension OpaquePointer {
/*Used to check if value pointed by the opaque pointer is nil (to silence compiler warnings as self == nil would also work)
It works by figuring out whether the pointer is a nil pointer, from it's debug description .*/
func isNil() -> Bool {
    return !self.debugDescription.contains { "123456789abcdef".contains($0.lowercased()) }
}

After that you only need to call turnOffGTMLogs() once (preferably in the same place where you initialise GTM, usually in AppDelegate) to silence the log outputs.

Here's a cleaned up version for Swift 5 as a class you can use in your AppDelegate like this:

GoogleTagManagerHelper.hideGTMLogs()

import Foundation

internal final class GoogleTagManagerHelper {

    enum LogLevel: String, CaseIterable {
        case info = "info:"
        case warning = "warning:"
    }

    static func hideGTMLogs() {
        LogLevel.allCases.forEach { hideGTMLogs(for: $0) }
    }

    static func hideGTMLogs(for level: GoogleTagManagerHelper.LogLevel) {
        let tagClass: AnyClass? = NSClassFromString("TAGLogger")
        let originalSelector = NSSelectorFromString(level.rawValue)
        let detourSelector = #selector(detour_log(message:))
        guard
            let originalMethod = class_getClassMethod(tagClass, originalSelector),
              let detourMethod = class_getClassMethod(GoogleTagManagerHelper.self, detourSelector)
        else { return }
        class_addMethod(
            tagClass,
            detourSelector,
            method_getImplementation(detourMethod),
            method_getTypeEncoding(detourMethod)
        )
        method_exchangeImplementations(originalMethod, detourMethod)
    }

    @objc static func detour_log(message: String) { return }
}

In Swift 5, to silent info & warning logs from GTAG automatically, just insert & call those two methods in your app delegate (hideGTMLogsInfo() & hideGTMLogsWarning()):

static func hideGTMLogsInfo() {
    let tagClass: AnyClass? = NSClassFromString("TAGLogger")

    let originalSelector = NSSelectorFromString("info:")
    let detourSelector = #selector(AppDelegate.detour_info(message:))

    guard let originalMethod = class_getClassMethod(tagClass, originalSelector),
        let detourMethod = class_getClassMethod(AppDelegate.self, detourSelector) else { return }

    class_addMethod(tagClass, detourSelector,
                    method_getImplementation(detourMethod), method_getTypeEncoding(detourMethod))
    method_exchangeImplementations(originalMethod, detourMethod)
}

static func hideGTMLogsWarning() {
    let tagClass: AnyClass? = NSClassFromString("TAGLogger")

    let originalSelector = NSSelectorFromString("warning:")
    let detourSelector = #selector(AppDelegate.detour_warning(message:))

    guard let originalMethod = class_getClassMethod(tagClass, originalSelector),
        let detourMethod = class_getClassMethod(AppDelegate.self, detourSelector) else { return }

    class_addMethod(tagClass, detourSelector,
                    method_getImplementation(detourMethod), method_getTypeEncoding(detourMethod))
    method_exchangeImplementations(originalMethod, detourMethod)
}

@objc
static func detour_warning(message: String) {
    return
}
@objc
static func detour_info(message: String) {
    return
}
Related