Skip to content

Track methods not generated (Browser Javascript) #98

@Zaimwa9

Description

@Zaimwa9

Hi,

I don't know where to ask my question. I've set up the new Data (beta) -To be honest I was happy with itly, anyways-. I have created events, pushed the latest version.

Even when I ampli pull, no methods are generated. I must use .track({event_type: "xx"}) which is completely opposed to why I wanted to implement data beta

Here is my generated ampli/index.js (without sensitive data) and below a screenshot of the tracking plan.

Please help 😄 It would be awesome!

image

import amplitude from 'amplitude-js';

/**
 * @typedef BaseEvent
 * @type {object}
 * @property {string} event_type
 * @property {Object.<string, *>} [event_properties]
 */

/**
 * @typedef Plan
 * @type {object}
 * @property {string} [branch]
 * @property {string} [source]
 * @property {string} [version]
 * @property {string} [versionId]
 */

/**
 * Data to be processed by middleware
 * @typedef MiddlewarePayload
 * @type {object}
 * @property {BaseEvent} event
 * @property {MiddlewareExtra} [extra]
 */

/**
 * Function called at the end of each Middleware to run the next middleware in the chain
 * @typedef MiddlewareNext
 * @type {function}
 * @param {MiddlewarePayload} payload
 *
 * @return
 */

/**
 * A function to run on the Event stream (each logEvent call)
 * @typedef Middleware
 * @type {function}
 * @param {MiddlewarePayload} payload The event and extra data being sent
 * @param {MiddlewareNext} next Function to run the next middleware in the chain, not calling next will end the middleware chain
 * @return
 */

/**
 * @typedef LoadClientOptions
 * @type {object}
 * @property {string} [apiKey]
 * @property {Object} [options]
 * @property {AmplitudeClient} [instance]
 */

/**
 * @typedef LoadOptions
 * @type {object}
 * @property {'development'|'production'} [environment]
 * @property {boolean} [disabled]
 * @property {LoadClientOptions} [client]
 */

/**
 * @typedef {Object} EventOptions
 * @type {object}
 */

/**
 * @typedef {Object} IdentifyOptions
 * @type {object}
 */

/**
 * @typedef {Object} GroupOptions
 * @type {object}
 */

/**
 * @typedef {Object} MiddlewareExtra
 * @type {Object.<string, *>}
 */

/**
 * @typedef ApiKey
 * @type {object}
 * @property {string} development
 * @property {string} production
 */
export const ApiKey = {
  development: '',
  production: ''
};

export const SpecialEventType = {
  Identify: "Identify",
  Group: "Group"
}

/**
 * Default Amplitude configuration options. Contains tracking plan information.
 */
export const DefaultOptions = {
  plan: {
    version: '8',
    branch: 'main',
    source: '',
    versionId: ''
  }
};

export class Identify {
  constructor() {
    this.event_type = 'Identify';
  }
}

export class Group {
  constructor() {
    this.event_type = 'Group';
  }
}

// prettier-ignore
export class Ampli {
  constructor() {
    /* @type {AmplitudeClient|undefined} */
    this.amplitude = undefined;
    this.disabled = false;
    /* @type {Middleware[]} */
    this.middlewares = [];
  }

  /**
   * @return {AmplitudeClient}
   */
  get client() {
    this.isInitializedAndEnabled();
    return this.amplitude;
  }

  /**
   * @private
   * @return {boolean}
   */
  isInitializedAndEnabled() {
    if (!this.amplitude) {
      throw new Error('Ampli is not yet initialized. Have you called ampli.load() on app start?');
    }
    return !this.disabled;
  }

  /**
   * Initialize the Ampli SDK. Call once when your application starts.
   * @param {LoadOptions} [options] Configuration options to initialize the Ampli SDK with.
   */
  load(options) {
    this.disabled = options?.disabled ?? false;

    if (this.amplitude) {
      console.warn('WARNING: Ampli is already intialized. Ampli.load() should be called once at application startup.');
      return;
    }

    const env = options?.environment ?? 'development';
    const apiKey = options?.client?.apiKey ?? ApiKey[env];

    if (options?.client?.instance) {
      this.amplitude = options?.client?.instance;
    } else if (apiKey) {
      this.amplitude = amplitude.getInstance();
      this.amplitude?.init(apiKey, undefined, { ...DefaultOptions, ...(options?.client?.options ?? options?.client?.config) });
    } else {
      throw new Error("ampli.load() requires 'environment', 'client.apiKey', or 'client.instance'");
    }
  }

  /**
   * Identify a user.
   *
   * @param {string|undefined} userId The user's id.
   * @param {IdentifyOptions} [options] Optional event options.
   * @param {MiddlewareExtra} [extra] Extra unstructured data for middleware.
   */
  identify(userId, options, extra) {
    if (!this.isInitializedAndEnabled()) {
      return;
    }

    const event = {
      event_type: SpecialEventType.Identify,
      user_id: userId || options?.user_id,
      device_id: options?.device_id
    };
    this.runMiddleware({ event, extra }, payload => {
      const e = payload.event;
      if (e.user_id) {
        this.amplitude.setUserId(e.user_id);
      }
      if (e.device_id) {
        this.amplitude.setDeviceId(e.device_id);
      }
      const ampIdentify = new amplitude.Identify();
      if (e.event_properties != null) {
        for (const [key, value] of Object.entries(e.event_properties)) {
          ampIdentify.set(key, value);
        }
      }
      this.amplitude.identify(
        ampIdentify,
        options?.callback,
        options?.errorCallback
      );
    });
  }

  /**
   * Set Group for the current user
   *
   * @param {String} name
   * @param {String|String[]} value
   * @param {GroupOptions} [options]
   * @param {MiddlewareExtra} [extra]
   */
  setGroup(name, value, options, extra) {
    if (!this.isInitializedAndEnabled()) {
      return;
    }

    this.amplitude?.setGroup(name, value);
  }

  /**
   * Identify a group.
   *
   * @param {string} groupType The group type.
   * @param {string|string[]} groupName The group name.
   * @param {GroupOptions} [options] Options for this groupIdentify call.
   * @param {MiddlewareExtra} [extra] Extra untyped parameters for use in middleware.
   */
  groupIdentify(groupType, groupName, options, extra) {
    if (!this.isInitializedAndEnabled()) {
      return;
    }

    const event = {
      event_type: SpecialEventType.Group,
      user_id: options?.user_id,
      device_id: options?.device_id
    };
    this.runMiddleware({ event, extra }, payload => {
      const e = payload.event;
      if (e.user_id) {
        this.amplitude.setUserId(e.user_id);
      }
      if (e.device_id) {
        this.amplitude.setDeviceId(e.device_id);
      }
      const amplitudeIdentify = new amplitude.Identify();
      if (e.event_properties != null) {
        for (const [key, value] of Object.entries(e.event_properties)) {
          amplitudeIdentify.set(key, value);
        }
      }
      this.amplitude.groupIdentify(groupType, groupName, amplitudeIdentify, options?.callback);
    });
  }

  /**
   * Track event
   *
   * @param {BaseEvent} event The event to track.
   * @param {EventOptions} [options] Optional event options.
   * @param {MiddlewareExtra} [extra] Extra unstructured data for middleware.
   */
  track(event, options, extra) {
    if (!this.isInitializedAndEnabled()) {
      return;
    }

    this.runMiddleware({ event, extra }, payload => {
      this.amplitude.logEvent(
        payload.event.event_type,
        payload.event.event_properties,
        options?.callback,
        options?.errorCallback,
      );
    });
  }

  /**
   * Add new middleware to end of chain
   *
   * @param {Middleware} middleware
   */
  addEventMiddleware(middleware) {
    this.middlewares.push(middleware);
  }

  /**
   * Runs all middleware
   *
   * @param {MiddlewarePayload} payload
   * @param {MiddlewareNext} next The method to run after all middleware.
   *
   * @protected
   */
  runMiddleware(payload, next) {
    let curMiddlewareIndex = -1;
    const middlewareCount = this.middlewares.length;

    const middlewareNext = curPayload => {
      curMiddlewareIndex += 1;
      if (curMiddlewareIndex < middlewareCount) {
        this.middlewares[curMiddlewareIndex](curPayload, _next);
      } else {
        next(curPayload);
      }
    };

    const _next = middlewareCount > 0 ? middlewareNext : next;

    _next(payload);
  }
}

export const ampli = new Ampli();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions