Skip to main content

Eventos de Survey

O SDK notifica seu app a cada evento da pesquisa — impressão, resposta, minimizar, envio, fecho — através de um closure listener opcional. Use-o para espelhar o funil no seu próprio analytics ou para reagir no app (ex.: dar um brinde depois que o usuário responde um NPS).

Registrar (ou não) um listener não afeta a coleta de dados da GoAB — o listener é só uma cópia dos eventos para o seu app.

Registrar e remover

addOnSurveyEventListener recebe um closure @escaping e retorna um handle que você guarda para remover depois.

import GoABSurveySDK

let handle = surveySdk.addOnSurveyEventListener { event in
switch event.eventType {
case .surveyImpression:
Analytics.track("survey_shown", ["survey_id": event.surveyId ?? 0])
case .questionAnswer:
Analytics.track("survey_question_answered", [
"survey_id": event.surveyId ?? 0,
"question_id": event.questionId ?? 0,
"question_type": event.questionType ?? "",
"answer": (event.answer as? [String])?.joined(separator: "|") ?? "",
])
case .surveySubmit:
Analytics.track("survey_completed", ["survey_id": event.surveyId ?? 0])
default:
break
}
}

// ao encerrar a tela / no logout:
surveySdk.removeOnSurveyEventListener(listener: handle)
  • Vários listeners podem coexistir.
  • Um erro lançado dentro do closure é capturado pelo SDK — não derruba a pesquisa nem os outros listeners.
  • Não assuma a main thread dentro do closure; use DispatchQueue.main.async se for tocar em UIKit.
  • Faça só trabalho leve no closure; mande processamento pesado para uma fila sua.
  • Guarde o handle e chame removeOnSurveyEventListener no fim do ciclo de vida (logout, deinit) para não vazar referências capturadas.

Assinatura

func addOnSurveyEventListener(
listener: @escaping (SurveyAnalyticsEvent) -> Void
) -> OnSurveyEventListener

func removeOnSurveyEventListener(listener: OnSurveyEventListener)

OnSurveyEventListener é um tipo opaco — serve só como handle de remoção. O parâmetro do closure é sempre um SurveyAnalyticsEvent.

SurveyAnalyticsEvent

Um evento da pesquisa. Nem todo campo é preenchido em todo evento — veja a coluna correspondente na tabela de tipos. Todos os campos, exceto eventType, são opcionais.

CampoTipo SwiftDescrição
eventTypeSurveyEventTypeO tipo do evento (enum, ver abaixo). Sempre presente.
surveyIdKotlinLong?ID da pesquisa. Presente em todos os eventos normais.
userIdString?ID do usuário definido via setUserId, ou nil se anônimo. Preenchido pelo SDK.
sessionIdString?ID da sessão atual. Muda no initialize() e a cada troca de userId. Preenchido pelo SDK.
timestampIsoString?Instante do evento em ISO-8601 (UTC).
timestampMillisKotlinLong?Instante do evento em epoch millis. Alternativa a timestampIso.
questionIdKotlinLong?ID da pergunta. Presente só em eventos de pergunta.
questionTypeString?Tipo da pergunta (ver tipos de pergunta). Presente só em eventos de pergunta.
answerAny?Resposta do usuário. Em tempo de execução é sempre um array de strings — leia com event.answer as? [String]. Escala/NPS chega como string numérica (ex.: ["9"]); múltipla escolha traz vários itens.
freeTextAnswerString?Texto digitado em campos de texto aberto, quando aplicável.

KotlinLong? é o boxing do Kotlin/Native para inteiro opcional — leia com event.surveyId?.int64Value quando precisar de um Int64.

Trabalhe sempre com os campos opcionais de forma defensiva (??, if let, switch event.eventType), lendo apenas o que a tabela de tipos garante para aquele evento.

Tipos de evento

SurveyEventType — enum exportado pelo SDK. Os nomes dos casos em Swift seguem camelCase. Cada caso tem um wireValue (string estável, útil para logar ou encaminhar o tipo ao seu analytics).

Caso SwiftwireValueQuando ocorreCampos preenchidos além de eventType / surveyId
.surveyImpressionsurvey_impressionA pesquisa apareceu na tela.sessionId, timestamp
.surveyInteractsurvey_interactInteração genérica com a pesquisa.timestamp
.surveyMinimizesurvey_minimizeUsuário minimizou a pesquisa.timestamp
.surveyMaximizesurvey_maximizeUsuário restaurou a pesquisa minimizada.timestamp
.surveyClosesurvey_closePesquisa fechada/dispensada sem envio.timestamp
.questionImpressionquestion_impressionUma pergunta ficou visível.questionId, questionType
.questionInteractquestion_interactUsuário mexeu num controle da pergunta (ainda sem confirmar).questionId, questionType, answer parcial
.questionAnswerquestion_answerUsuário respondeu uma pergunta.questionId, questionType, answer e/ou freeTextAnswer
.questionSkipquestion_skipPergunta pulada.questionId, questionType
.surveyAnswersurvey_answerResposta consolidada da pesquisa.answer
.surveySubmitsurvey_submitUsuário concluiu e enviou a pesquisa.sessionId, timestamp

Tipos de pergunta

Valores possíveis de questionType:

questionTypeSignificadoConteúdo de answer
radioEscolha única1 item — o texto da opção
selectDropdown de escolha única1 item
checkboxMúltipla escolha1+ itens
npsNota NPS (0–10)1 item — a nota como string (["10"])
rating / scale / star / emojiNota / escala1 item — a nota como string
textTexto livreo texto digitado (em answer e/ou freeTextAnswer)

Exemplo: acompanhar o funil da pesquisa

final class SurveyFunnelTracker {

private var handle: OnSurveyEventListener?

func attach(to surveySdk: SurveySdk) {
handle = surveySdk.addOnSurveyEventListener { [weak self] event in
self?.handle(event)
}
}

func detach(from surveySdk: SurveySdk) {
if let handle { surveySdk.removeOnSurveyEventListener(listener: handle) }
handle = nil
}

private func handle(_ event: SurveyAnalyticsEvent) {
let base: [String: Any] = [
"survey_id": event.surveyId ?? 0,
"session_id": event.sessionId ?? "",
]
switch event.eventType {
case .surveyImpression:
Analytics.track("survey_impression", base)
case .questionAnswer:
Analytics.track("survey_question_answered", base.merging([
"question_id": event.questionId ?? 0,
"question_type": event.questionType ?? "",
"answer": (event.answer as? [String])?.joined(separator: "|") ?? "",
]) { _, new in new })
case .surveySubmit:
Analytics.track("survey_completed", base)
case .surveyClose:
Analytics.track("survey_abandoned", base)
default:
break
}
}
}

Próximos passos